spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解

引用这位大佬的文章基础进行补充:https://www.jianshu.com/p/1dec08d290c1

  1. 实例化 Instantiation
  2. 属性赋值 Populate
  3. 初始化 Initialization
  4. 销毁 Destruction

第一大类:影响多个Bean的接口

实现了这些接口的Bean会切入到多个Bean的生命周期中。正因为如此,这些接口的功能非常强大,Spring内部扩展也经常使用这些接口,例如自动注入以及AOP的实现都和他们有关。

  • BeanPostProcessor
  • InstantiationAwareBeanPostProcessor

这两兄弟可能是Spring扩展中最重要的两个接口!InstantiationAwareBeanPostProcessor作用于实例化阶段的前后,BeanPostProcessor作用于初始化阶段的前后。正好和第一、第三个生命周期阶段对应。通过图能更好理解:

上面已经很清楚的表明这俩个接口的作用了

下一步我们来看这两个接口是何时加入到BeanFactory里面的和何时被调用的

1.首先看一下接口的类图:

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第1张图片

InstantiationAwareBeanPostProcessor继承BeanPostProcessor所以InstantiationAwareBeanPostProcessor具有BeanPostProcessor的功能,在测试的时候一定要注意InstantiationAwareBeanPostProcessor重写的方法名,我就是因为重写的方法错误,造成测试的时候结果一样,卡了一段时间。

2.接口何时别加入进去的

新加测试代码

@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模式调试

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第2张图片

从调用栈可以看到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

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第3张图片

原来是在

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);

3.接口是何时调用的,两个接口有什么区别

新增测试类Test,加上@Component,并且作为UserService的属性,加上@Autowired注解

@Component
public class Test {
}
@Component
public class UserService {
	@Autowired
	private Test test;



	public void test() {
		System.out.println("test");
	}

}

其实就是查看两个接口在bean哪个阶段调用

还是按上面方法在自己测试类里面打上断点启动

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第4张图片

查看调用栈针可以看到是在创建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方法里面

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第5张图片

重点看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重写的方法里面

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第6张图片

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第7张图片

可以看到不管初始化前还是初始化后test都是已经有值了的,因为初始化是属性填充后的步骤,所以都是有值的。再看控制台输出结果

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第8张图片

由此可以知道一个是在初始前一个是在初始化后。

注意 注意 注意:一定不要把TestInstantiationAwareBeanPostProcessor和TestBeanPostProcessors这个两个bean都注入到beanFactory里面,一个个开启@Component测试,如果要注入,则必须把TestInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(params)的返回结果改成true,如果没有,在TestBeanPostProcessors方法里面的test一直为空,测不出什么效果,我这里卡了半个小时。

咱们来看TestInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(params)是什么意思:

spring Bean 生命周期及BeanPostProcessor和InstantiationAwareBeanPostProcessor详解_第9张图片

总结:在初始化new AnnotationConfigApplicationContext(AppConfig.class);时候会在

refresh();方法里面的
// Instantiate all remaining (non-lazy-init) singletons.
// 完成beanFactory的初始化(实例化非懒加载的单例bean)
finishBeanFactoryInitialization(beanFactory);

实例化Bean的时候会调用上面接口的回调。

4.执行顺序

借用上面博主的文字

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();

下一节后续的后置接口详解

你可能感兴趣的:(spring,源码阅读,spring,bean,ioc,java)