fish-stack / JavaWeb

Java web开发相关的技能
0 stars 0 forks source link

Stack Overflow上关于Spring的一些问答 #18

Open bitfishxyz opened 5 years ago

bitfishxyz commented 5 years ago

<context:annotation-config> and <context:component-scan>之间有什么区别?

https://stackoverflow.com/questions/7414794/difference-between-contextannotation-config-vs-contextcomponent-scan)


<context:annotation-config>表明,对于已经注册到容器中的bean,Spring将会监测这些bean上的注解,并作出处理

假如有这样的类,动物园的一只大熊猫

package zoo.animal;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter @Setter
@NoArgsConstructor
@AllArgsConstructor
public class Panda {
    private String name;
    private Float weight;
}

然后有一个熊猫守望者:

@Getter @Setter
@NoArgsConstructor
public class PandaWatcherAnnotation {
    private String name;

    @Autowired
    private Panda panda;
}

在熊猫守望者身上有@Autowire这个注解。

然后我们写出这样的配置文件

    <!--<context:annotation-config/>-->

    <bean name="panda" class="zoo.animal.Panda" p:name="panda"/>

    <bean name="pandaWatcher" class="zoo.annotation.PandaWatcherAnnotation">
        <property name="name" value="watcher"/>
    </bean>

那么大家觉得我通过容器创建pandaWatcher后,它的属性有没有被注入panda?

答案是否定的,我们需要在配置文件中开启注解模式后,Spring才会处理这个注解。写成这样就行了

    <context:annotation-config/>

    <bean name="panda" class="zoo.animal.Panda" p:name="panda"/>

    <bean name="pandaWatcher" class="zoo.annotation.PandaWatcherAnnotation">
        <property name="name" value="watcher"/>
    </bean>

<context:component-scan>这个配置是开启注解扫描。有了它之后你就不用再配置文件中配置bean了,可以直接在Java代码中给相关的类标注为@Component @Repository。。。

然后呢,你开启<context:component-scan>之后,<context:annotation-config>默认也是会被开启的。

bitfishxyz commented 5 years ago

@Inject 和@Autowired之间有什么区别?

https://stackoverflow.com/questions/7142622/what-is-the-difference-between-inject-and-autowired-in-spring-framework-which


@Injectjavax.inject.Inject)是JSR-299提出的标准,用来规范依赖注入的语法。

而@Autowired是Spring自带的用于依赖注入的注解。

Spring设计者选择让@Autowired兼容@Inject,二者可以基本互换。唯一的区别是@Autowired比@Inject多了一个required属性。

如果你想使用@Inject,需要引入下面的依赖

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

那么,这两个注解我用谁呢?就想豆腐脑是甜的还是咸的,SO网友有激烈的讨论。

支持@Inject的

支持@Autowired的

bitfishxyz commented 5 years ago

为什么通过@Autowired注解的字段的值是null?

https://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null

接上面的例子,我通过这样的方式创建熊猫守望者,为什么发现结果是null?

        PandaWatcherAnnotation pandaWatcher = new PandaWatcherAnnotation();
        System.out.println(pandaWatcher.getPanda());

因为@Autowired之类的注解必须由IOC容器来管理才会生效,你要是通过new的方式创建,这其实是跳过了依赖注入的阶段,所以结果是null。

bitfishxyz commented 5 years ago

在Spring中,Bean到底是什么含义?

https://stackoverflow.com/questions/17193365/what-in-the-world-are-spring-beans

我已经非常熟练的使用Spring了,但我还是搞不清楚Bean究竟意味着什么,谁能解释一下?


你的应用程序中,被Sping Ioc容器管理的对象都称之为Bean。每个Bean的实例化、组装。。。都是由Spring来管理的。

bitfishxyz commented 5 years ago

什么时候使用Bean Factory,什么时候使用Application Context

https://stackoverflow.com/questions/243385/beanfactory-vs-applicationcontext

我知道ApplicationContext 继承自 BeanFactory,但是到底如何选择呢?


Sping的官方文档以及有了解释了: 3.8.1. BeanFactory or ApplicationContext?. 我来总结下

Bean Factory

Application Context

So if you need any of the points presented on the Application Context side, you should use ApplicationContext.

bitfishxyz commented 5 years ago

如何在bean中获得容器本身的引用?

https://stackoverflow.com/questions/129207/getting-spring-application-context


很简单,直接自动装配就行了

@Getter @Setter
@NoArgsConstructor
public class Sheep {
    private String name;

    @Autowired
    private ApplicationContext context;
}

给bean一个ApplicationContext类型的属性,然后自动装配就行了。

public class SheepAnnotationTest {
    private static ApplicationContext context;
    @BeforeClass
    public static void getContext(){
        context = new ClassPathXmlApplicationContext("ioc/annotation/spring.xml");
    }

    @Test
    public void autowire(){
        Sheep sheep = context.getBean("sheep", Sheep.class);

        System.out.println(sheep.getContext() == context);
        // true
    }
}

或者可以让我们的bean实现ApplicationContextAware这个接口

@Getter @Setter
@NoArgsConstructor
public class Fish implements ApplicationContextAware {
    private String name;

    private ApplicationContext context;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}

这样容器在初始化的时候就会调用这个方法,并且把ApplicationContext作为参数传递进去

        Fish fish = context.getBean("fish", Fish.class);
        System.out.println(fish.getContext() == context);
        // true
bitfishxyz commented 5 years ago

如何在context:component-scan中,同时扫描多个包?

https://stackoverflow.com/questions/5269450/multiple-packages-in-contextcomponent-scan-spring-config


类似于下面这样

<context:component-scan base-package="x.y.z.service, x.y.z.controller" />