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

Bean的生命周期

java
@Slf4j
@Component
public class LifeCycleBean {

    public LifeCycleBean() {
        log.info("构造");
    }

    @Autowired
    public void autowire(@Value("${JAVA_HOME}") String home) {
        log.info(" autowired JAVA_HOME {}", home);
    }

    @PostConstruct
    public void init() {
        log.info("初始化");
    }

    @PreDestroy
    public void destroy() {
        log.info("销毁");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

我们都知道实例化Bean以后会调用@PostConstruct,销毁前会掉@PreDestroy所修饰的方法。

java
@Slf4j
@Component
public class LifeCycleBeanPostProcessor 
    implements InstantiationAwareBeanPostProcessor, 
	DestructionAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            log.info("---- 实例化之前执行,这里返回的对象会替换原本的Bean ");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            log.info("---- 实例化之后执行,这里返回false 会跳过依赖注入阶段 ");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            log.info("---- 依赖注入阶段 @Autowired @Value @Resource");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            log.info("---- 初始化之前执行,这里返回的对象会替换掉原本的Bean 如@PostConstruct @ConfigurationProperties ");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            log.info("---- 初始化之后执行,这里返回的对象会替换掉原本的Bean 代理增强 ");
        }
        return bean;
    }

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if ("lifeCycleBean".equals(beanName)) {
            log.info("---- 销毁之前执行 ");
        }
    }

}
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
shell
# 打印结果
[           main] com.laoshiren.app.App                    : Starting App using Java 1.8.0_181 on laoshiren with PID 20392 (D:\laoshiren\spring-bean-init\target\classes started by laoshiren in D:\laoshiren\spring-bean-init)
[           main] com.laoshiren.app.App                    : No active profile set, falling back to default profiles: default
[           main] c.l.a.l.LifeCycleBeanPostProcessor       : ---- 实例化之前执行,这里返回的对象会替换原本的Bean 
[           main] c.laoshiren.app.lifecycle.LifeCycleBean  : 构造
[           main] c.l.a.l.LifeCycleBeanPostProcessor       : ---- 实例化之后执行,这里返回false 会跳过依赖注入阶段 
[           main] c.l.a.l.LifeCycleBeanPostProcessor       : ---- 依赖注入阶段 @Autowired @Value @Resource
[           main] c.laoshiren.app.lifecycle.LifeCycleBean  :  autowired JAVA_HOME C:\Program Files\Java\jdk1.8.0_181
[           main] c.l.a.l.LifeCycleBeanPostProcessor       : ---- 初始化之前执行,这里返回的对象会替换掉原本的Bean 如@PostConstruct @ConfigurationProperties 
[           main] c.laoshiren.app.lifecycle.LifeCycleBean  : 初始化
[           main] c.l.a.l.LifeCycleBeanPostProcessor       : ---- 初始化之后执行,这里返回的对象会替换掉原本的Bean 代理增强 
[           main] com.laoshiren.app.App                    : Started App in 0.727 seconds (JVM running for 1.27)
[           main] c.l.a.l.LifeCycleBeanPostProcessor       : ---- 销毁之前执行 
[           main] c.laoshiren.app.lifecycle.LifeCycleBean  : 销毁
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Bean 后置处理器

java
public class Component2 {
}

public class Component3 {
}

@Slf4j
@Data
public class Component1 {
    
    public Component1() {
        log.info("构造");
    }

    private Component2 component2;

    @Autowired
    public void setComponent2(Component2 component2){
        log.info("@Autowired 生效 ");
        this.component2 = component2;
    }

    private Component3 component3;

    @Resource
    public void setComponent3(Component3 component3) {
        log.info("@Resource 生效 ");
        this.component3 = component3;
    }

    private String home;

    @Autowired
    public void setHome(@Value("${JAVA_HOME}") String home) {
        log.info("@Value 生效 {}", home);
        this.home = home;
    }

    @PostConstruct
    public void init() {
        log.info("初始化");
    }

    @PreDestroy
    public void destroy() {
        log.info("销毁");
    }
}
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
37
38
39
40
41
42
43
44
45
46
47
48

常见的Bean 后置处理器

GenericApplicationContext 是一个【干净】的容器, 没有添加额外的BeanFactory后置处理器 Bean后置处理器

AutowiredAnnotationBeanPostProcessor 用于解析@Autowired @Value

java
public class MyBeanPostProcessorMain {

    public static void main(String[] args) {
        // GenericApplicationContext 是一个【干净】的容器, 没有添加额外的BeanFactory后置处理器 Bean后置处理器
        GenericApplicationContext ctx = new GenericApplicationContext();
        // 注册Bean
        ctx.registerBean("component1", Component1.class);
        ctx.registerBean("component2", Component2.class);
        ctx.registerBean("component3", Component3.class);
        // 默认的解析器不能解析@Value 值注入 所以使用其他的解析器
        ctx.getDefaultListableBeanFactory()
                .setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 注册AutowiredAnnotationBeanPostProcessor
        // 解析@Autowired @Value 注解
        ctx.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        // 初始化容器
        ctx.refresh();
        ctx.close();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
shell
# 打印结果
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'component1'
[main] INFO com.laoshiren.app.bean.Component1 - 构造
[main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'JAVA_HOME' in PropertySource 'systemEnvironment' with value of type String
[main] INFO com.laoshiren.app.bean.Component1 - @Value 生效 C:\Program Files\Java\jdk1.8.0_181
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'component2'
[main] INFO com.laoshiren.app.bean.Component1 - @Autowired 生效 
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'component3'
1
2
3
4
5
6
7
8

CommonAnnotationBeanPostProcessor用于解析@Resource@PostConstruct@PreDestory,注册Beanctx.registerBean(CommonAnnotationBeanPostProcessor.class);

shell
# 打印结果
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'component1'
[main] INFO com.laoshiren.app.bean.Component1 - 构造
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'component3'
[main] INFO com.laoshiren.app.bean.Component1 - @Resource 生效 
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'component2'
[main] INFO com.laoshiren.app.bean.Component1 - @Autowired 生效 
[main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'JAVA_HOME' in PropertySource 'systemEnvironment' with value of type String
[main] INFO com.laoshiren.app.bean.Component1 - @Value 生效 C:\Program Files\Java\jdk1.8.0_181
[main] INFO com.laoshiren.app.bean.Component1 - 初始化
[main] DEBUG org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@7dc5e7b4, started on Wed Jan 11 14:04:49 CST 2023
[main] INFO com.laoshiren.app.bean.Component1 - 销毁
1
2
3
4
5
6
7
8
9
10
11
12

Springboot 中的Bean后置处理器

java
@ConfigurationProperties(prefix = "java")
@Data
public class Bean4Properties {

    private String home;

    private String version;

}
1
2
3
4
5
6
7
8
9

Springboot中的后置处理器 用于解析@ConfigurationProperties

java
public class MyBeanPostProcessorMain {
	public static void main(String[] args) {
        GenericApplicationContext ctx = new GenericApplicationContext();
        // 注册Bean
        ctx.registerBean("bean4Properties", Bean4Properties.class);
        // Springboot中的后置处理器 用于解析@ConfigurationProperties
     ConfigurationPropertiesBindingPostProcessor.register(ctx.getDefaultListableBeanFactory());
        // 初始化容器
        // 执行BeanFactory 后置处理器
        ctx.refresh();
        ctx.close();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

a.png

关于执行顺序,我们都知道Spring中会对这些进行排序,排序规则来自各种PostProcessor 实现的Order 接口

java
public interface Ordered {
    // -2147483648
	int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
    // 2147483647
	int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

	int getOrder();
}
1
2
3
4
5
6
7
8
BeanPostProcessorOrder
CommonAnnotationBeanPostProcessorOrdered.LOWEST_PRECEDENCE - 3
AutowiredAnnotationBeanPostProcessorOrdered.LOWEST_PRECEDENCE - 2
ConfigurationPropertiesBindingPostProcessorOrdered.HIGHEST_PRECEDENCE + 1

AutowiredAnnotationBeanPostProcessor

java
public class MyDebugAutowiredAnnotationBeanPostProcessor {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 因为传入的是一个对象所以,不会执行创建过程,依赖注入,初始化过程
        beanFactory.registerSingleton("component2", new Component2());
        beanFactory.registerSingleton("component3", new Component3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        
        AutowiredAnnotationBeanPostProcessor postProcessor = new AutowiredAnnotationBeanPostProcessor();
        postProcessor.setBeanFactory(beanFactory);
        
        Component1 component1 = new Component1();
        // 依赖注入阶段调用 解析@Autowired @Value
        postProcessor.postProcessProperties(null, component1,"component1");
        System.out.println(component1);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

a.png

AutowiredAnnotationBeanPostProcessor.png
java
public class MyDebugAutowiredAnnotationBeanPostProcessor {

    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 因为传入的是一个对象所以,不会执行创建过程,依赖注入,初始化过程
        beanFactory.registerSingleton("component2", new Component2());
        beanFactory.registerSingleton("component3", new Component3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

        AutowiredAnnotationBeanPostProcessor postProcessor = new AutowiredAnnotationBeanPostProcessor();
        postProcessor.setBeanFactory(beanFactory);
        Component1 component1 = new Component1();
        // 依赖注入阶段调用 解析@Autowired @Value
        postProcessor.postProcessProperties(null, component1,"component1");
        System.out.println(component1);

        // 修饰属性查找值
        Field component2 = Component1.class.getDeclaredField("component2");
        DependencyDescriptor dependencyDescriptorField = new DependencyDescriptor(component2, false);
        Object propertiesBean = beanFactory.doResolveDependency(dependencyDescriptorField, null, null, null);
        System.out.println(propertiesBean);

        // 方法查找值
        Method setComponent2 = Component1.class.getDeclaredMethod("setComponent2", Component2.class);
        DependencyDescriptor dependencyDescriptorMethod =
                new DependencyDescriptor(new MethodParameter(setComponent2,0),false);
        Object methodFindBean = beanFactory.doResolveDependency(dependencyDescriptorMethod, null, null, null);

        System.out.println(methodFindBean);
    }

}
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

Released under the MIT License.