Skip to content
On this page

Spring 第五讲 Bean

pom.xml 准备

xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/>
    </parent>

    <groupId>org.laoshiren</groupId>
    <artifactId>spring-bean-init</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Aware和 InitializingBean

Aware

Aware 接口用于注入一些与容器相关的信息例如

  • BeanNameAware 注入的BeanName
  • BeanFactoryAware 注入的Beanfactory
  • ApplicationContextAware 注入的ApplicationContext
  • EmbeddedValueResolverAware ${}
java
public class BeanNameAwareBean implements BeanNameAware, BeanFactoryAware,
        ApplicationContextAware, EmbeddedValueResolverAware {

    @Override
    public void setBeanName(String name) {
        System.out.println("name:" +name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext:"+ applicationContext.getClass());
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("beanFactory:"+ beanFactory.getClass());
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {

    }

    @Autowired
    public void laoshiren(ApplicationContext applicationContext){
        System.out.println("注解的方式 applicationContext:"+ applicationContext.getClass());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
shell
# 打印结果
name:myBean
beanFactory:class org.springframework.beans.factory.support.DefaultListableBeanFactory
applicationContext:class org.springframework.context.support.GenericApplicationContext
1
2
3
4

InitializingBean

给我们实现这个接口的类做初始化方法的接口

java
public class InitializingRealBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化 ");
    }

    @PostConstruct
    public void init(){
        System.out.println("注解的方式");
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
shell
# 打印结果
初始化
1
2

这些接口的执行是在BeanPostProcessor 执行之后执行的

为什么有了@Autowired 还需要Aware接口

@Autowired注解属于扩展功能,实际是通过Bean 的后置处理器去解决,而Aware接口属于内置功能,并不需要扩展,Spring本身就能识别,而内置的功能永远不会失效。

我们的程序中没有加载各种BeanPostProcessor 所以导致不识别对应的注解

java
public class AwareMain {

    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        context.registerBean(CommonAnnotationBeanPostProcessor.class);
        
        context.registerBean("myBean", BeanNameAwareBean.class);
        context.registerBean("myInitBean", InitializingRealBean.class);
        context.refresh();
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

@Autowired 依然失效

我们的配置类在家@Bean 对应的BeanFactoryPostProcessor 之前是完全没有问题的

java
@Configuration
public class AutowireNotWorkConfig {

    @Autowired
    public void setApplication(ApplicationContext applicationContext){
        System.out.println("application" + applicationContext.getClass());
    }

    @PostConstruct
    public void init(){
        System.out.println("初始化");
    }

    @Bean
    public BeanFactoryPostProcessor postProcessor1(){
        return postProcessor1->{
            System.out.println("hello ");            
        };
    }
    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Java 配置类包含BeanFactoryPostProcessor 的情况下,因为要创建其中的后置处理器的前提必须创建Java 配置类,而此时Bean后置处理器还未准备好,导致@Autowired 失效,注册后处理器在前,而@Autowired 注解在后,所以会导致此类的注解失效。

其他

@PostConstruct 、InitializingBean 和 @Bean(initMethod = "init") 三种方法的优先级?

  1. @PostConstruct 因为是Bean 的后置处理器执行的
  2. InitializingBean
  3. @Bean 是定义成BeanDefinition 后在执行的

Released under the MIT License.