引用这位大佬的文章基础进行补充:https://www.jianshu.com/p/1dec08d290c1
实现了这些接口的Bean会切入到多个Bean的生命周期中。正因为如此,这些接口的功能非常强大,Spring内部扩展也经常使用这些接口,例如自动注入以及AOP的实现都和他们有关。
这两兄弟可能是Spring扩展中最重要的两个接口!InstantiationAwareBeanPostProcessor作用于实例化阶段的前后,BeanPostProcessor作用于初始化阶段的前后。正好和第一、第三个生命周期阶段对应。通过图能更好理解:
上面已经很清楚的表明这俩个接口的作用了
下一步我们来看这两个接口是何时加入到BeanFactory里面的和何时被调用的
InstantiationAwareBeanPostProcessor继承BeanPostProcessor所以InstantiationAwareBeanPostProcessor具有BeanPostProcessor的功能,在测试的时候一定要注意InstantiationAwareBeanPostProcessor重写的方法名,我就是因为重写的方法错误,造成测试的时候结果一样,卡了一段时间。
新加测试代码
@Component
public class TestBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return null;
}
}
public class TestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return false;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
}
}
在TestInstantiationAwareBeanPostProcessor重写的方法打上断点,利用debug模式调试
从调用栈可以看到BeanFactory中的((DefaultListableBeanFactory)this).beanPostProcessors已经存在了我们测试的Bean.
再次进入getBeanPostProcessors()里面
public List getBeanPostProcessors() {
return this.beanPostProcessors;
}
找到beanPostProcessors是怎么加入的
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
// 根据equals方法来判断是否相等并移除
this.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// Add to end of list
// 添加在list的最后,到时候会按添加的顺序执行
this.beanPostProcessors.add(beanPostProcessor);
}
打上断点,启动运行一直F9直到上面测试BeanPostProcessor进入到((DefaultListableBeanFactory)this).beanPostProcessors
原来是在
new AnnotationConfigApplicationContext(AppConfig.class);
初始化的refresh(); 里面有
// Register bean processors that intercept bean creation.
// 从BeanFactory找出扫描得到得BeanPostProcessor,实例化并注册到BeanFactory中 registerBeanPostProcessors(beanFactory);
((DefaultListableBeanFactory)beanFactory).beanDefinitionMap里面,下面只是根据类型去取而已
总结:自己写的BeanPostProcessor会在创建AnnotationConfigApplicationContext时候在refresh()方法里面扫面得到然后注册到BeanFactory的属性beanPostProcessors里面。下面就是找出BeanPostProcessor的语句,其实就是在上一节注册Bean到bean工厂的时候就已经注册到BeanFactory的
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
新增测试类Test,加上@Component,并且作为UserService的属性,加上@Autowired注解
@Component
public class Test {
}
@Component
public class UserService {
@Autowired
private Test test;
public void test() {
System.out.println("test");
}
}
其实就是查看两个接口在bean哪个阶段调用
还是按上面方法在自己测试类里面打上断点启动
查看调用栈针可以看到是在创建AnnotationConfigApplicationContext时候在refresh()里
// Instantiate all remaining (non-lazy-init) singletons.
// 完成beanFactory的初始化(实例化非懒加载的单例bean)
finishBeanFactoryInitialization(beanFactory);
最后在
createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
(后续单独在写createBean方法的源码讲解)
实例化前
protected Object applyBeanPostProcessorsBeforeInstantiation(Class> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
调用的,按照这样的方法同理知道TestBeanPostProcessors什么时候调用
这里我们可以看出InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(Class> beanClass, String beanName)的参数跟postProcessAfterInstantiation(Object bean, String beanName)不同,一个是Class>一个是Object,因为postProcessBeforeInstantiation方法是在实例化前,还没有生成对象,而postProcessAfterInstantiation方法是在实例化后,已经有了对象只是没有初始化。
继续往下面走直到到beanName=userService时的postProcessAfterInstantiation方法里面
重点看UserService里面的Testl类型属性为空,看上面流程图就可以得知对象还没有初始化,所以证明是在实例化时切入
咱们在TestBeanPostProcessors调用式,bean的效果
为了事情进展的顺利咱们UserService类需要实现InitializingBean接口重写afterPropertiesSet()方法
@Component
public class UserService implements InitializingBean {
@Autowired
private Test test;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean.afterPropertiesSet()-------------");
}
public void test() {
System.out.println("test");
}
}
继续断点到TestBeanPostProcessors重写的方法里面
可以看到不管初始化前还是初始化后test都是已经有值了的,因为初始化是属性填充后的步骤,所以都是有值的。再看控制台输出结果
由此可以知道一个是在初始前一个是在初始化后。
注意 注意 注意:一定不要把TestInstantiationAwareBeanPostProcessor和TestBeanPostProcessors这个两个bean都注入到beanFactory里面,一个个开启@Component测试,如果要注入,则必须把TestInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(params)的返回结果改成true,如果没有,在TestBeanPostProcessors方法里面的test一直为空,测不出什么效果,我这里卡了半个小时。
咱们来看TestInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(params)是什么意思:
总结:在初始化new AnnotationConfigApplicationContext(AppConfig.class);时候会在
refresh();方法里面的
// Instantiate all remaining (non-lazy-init) singletons.
// 完成beanFactory的初始化(实例化非懒加载的单例bean)
finishBeanFactoryInitialization(beanFactory);
实例化Bean的时候会调用上面接口的回调。
借用上面博主的文字
BeanPostProcessor有很多个,而且每个BeanPostProcessor都影响多个Bean,其执行顺序至关重要,必须能够控制其执行顺序才行。关于执行顺序这里需要引入两个排序相关的接口:PriorityOrdered、Ordered
PriorityOrdered是一等公民,首先被执行,PriorityOrdered公民之间通过接口返回值排序
Ordered是二等公民,然后执行,Ordered公民之间通过接口返回值排序
都没有实现是三等公民,最后执行
在以下源码中,可以很清晰的看到Spring注册各种类型BeanPostProcessor的逻辑,根据实现不同排序接口进行分组。优先级高的先加入,优先级低的后加入。
作者:sunshujie1990
链接:https://www.jianshu.com/p/1dec08d290c1
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
源码:
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
下一节后续的后置接口详解