【Spring】Spring的PostProcessor-后

PostProcessor

为什么要有这个后置处理器这种接口,了解Spring容器的朋友应该知道,所有的ApplicationContext都需要调用AbstractApplicationContext#refresh方法,这是一个模板方法,既然使用了模板方法设计模式,那么就应该提供hook,也就是钩子函数。而PostProcessor就是为了实现这种定制化的扩展需求而制定的。

UML

  • BeanPostProcessor
    BeanPostProcessor
  • BeanFactoryPostProcessor

BeanFactoryPostProcessor

PostProcessor概览

BeanFactoryPostProcessor

容器级别的后置处理器,其内部仅声明了一个方法。Spring会根据声明的顺序对后置处理器进行调用,而BeanFactoryPostProcessor会在容器初始化期间将容器本身交由接口实现类去处理。获取到了容器,就可以做很多定制化的操作了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
java复制代码@FunctionalInterface
public interface BeanFactoryPostProcessor {

/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
BeanDefinitionRegistryPostProcessor

从注解容器解析BeanDefinition的篇章中,你会了解到BeanDefinitionRegistryPostProcessor是一种特殊的BeanFactoryPostProcessor,但是Spring会优先处理这类后置处理器,再处理常规的一些BeanFactoryPostProcessor.可以理解成VIP级别的BeanFactoryPostProcessor,优先于常规BeanFactoryPostProcessor执行。

其内部也声明了一个专用的注册后置处理方法。postProcessBeanDefinitionRegistry

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

BeanPostProcessor

容器创建Bean时的hook实例,你可以通过实现BeanPostProcessor来影响所有Bean的生命周期,包括Initialization的前置与后置处理.在后面学习Spring Bean的生命周期中,会接触BeanPostProcessor

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码public interface BeanPostProcessor {

@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

}

使用postProcessor

MyBeanFactoryPostProcessor

  • 基础对象
1
2
3
4
5
6
7
8
9
java复制代码@Data
public class Root {

private String name;

private String description;

private boolean isRoot;
}
  • 通过后置处理器往容器注入BeanDefinition
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
java复制代码package com.xjm.bean.postprocessor;

import com.xjm.model.Root;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.annotation.Configuration;

/**
* @author jaymin
* 2021/1/7 23:10
*/
@Configuration
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

}

/**
* 标准初始化后,修改应用程序上下文的内部BeanDefiniton注册表。<br>
* 所有常规bean定义都将被加载,但尚未实例化任何bean。 <br>
* 这允许在下一个后处理阶段开始之前添加更多的BeanDeinition。 <br>
* Spring工厂级别的BeanFactoryPostProcessor,优先级别高于常规的BeanFactoryPostProcessor.<br>
* 第三方框架整合时,可以实现这个注册接口进行BeanDefinition注册.如Mybatis.<br>
* 设计模式:责任链模式<br>
* @param registry the bean definition registry used by the application context
* @throws BeansException
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinition beanDefinition = getBeanDefinition(Root.class);
registry.registerBeanDefinition("root",beanDefinition);
System.out.println("Customer BeanPostProcessors execute.");
}

private BeanDefinition getBeanDefinition(Class<?> clazz){
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(clazz).getBeanDefinition();
return beanDefinition;
}
}
  • test

@ComponentScan根据自己的包路径进行修改,此处程序正常运行,说明Root已经注册到容器中了.

1
2
3
4
5
6
7
8
java复制代码@Configuration
@ComponentScan(value = "com.xjm")
public class BeanDefinitionDemoByAnnotation {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextDemo.class);
Root root = applicationContext.getBean("root", Root.class);
}
}

MyBeanPostProcessor

简单实现BeanPostProcessor,主要是观察其行为的作用域.

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
java复制代码@Configuration
public class MyBeanPostProcessor implements BeanPostProcessor {

@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + " invoking MyBeanPostProcessor#postProcessBeforeInitialization");
return bean;
}

/**
* 可以对所有的Bean做统一操作
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
@Nullable
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + " invoking MyBeanPostProcessor#postProcessAfterInitialization");
return bean;
}

}
  • result

result

可以看到,实现的MyBeanPostProcessor影响了所有Bean的初始化过程.

总结

  • 后置处理器是Spring留给开发者的扩展性钩子接口。
  • 从后置处理器上可以简略分为:BeanFactoryPostProcessorBeanPostProcessor.其中,BeanFactoryPostProcessor可以操作容器,BeanPostProcessor会影响所有Bean的生命周期.
  • BeanDefinitionRegistryPostProcessor是一种特殊的BeanFactoryPostProcessor,优于其他BeanFactoryPostProcessor执行.

扩展阅读

Spring系列六:Spring BeanPostProcessor

谈谈Spring中的BeanPostProcessor接口

Spring 执行顺序:PostProcessor 接口

Spring BeanPostProcessor

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%