逆向 Spring 源码系列(九)- 确认构造方法
2023-11-18 22:44:49
前言
创建Bean实例之二,确定构造方法。上一篇讲解了如何对Bean进行依赖自动注入和实例化。本次继续对createBeanInstance方法进行解析。Spring是如何根据BeanDefinition确定其构造函数呢?这将涉及到我们之前提到的BeanPostProcessor。
determineConstructorsFromBeanPostProcessors
查看源码发现,该方法的代码不算复杂:
public static BeanWrapperImpl determineConstructorsFromBeanPostProcessors(
Object bean, String beanName, BeanCreationException cause,
InstantiationAwareBeanPostProcessorProvider instantiationAwareBeanPostProcessorProvider) {
BeanPostProcessor bp = instantiationAwareBeanPostProcessorProvider.getEarlyBeanPostProcessor();
if (bp != null && !beanName.startsWith(
BeanFactoryPostProcessor.POST_PROCESSOR_BEAN_NAME_PREFIX)) {
return bp.postProcessBeforeInstantiation(beanClass, beanName);
}
return null;
}
该方法从BeanPostProcessorProvider中获取所有的实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor,如果找到了,则直接调用其postProcessBeforeInstantiation方法。这个方法可以对Bean的实例化操作进行拦截,其返回值如果为null,说明要使用默认方式进行实例化,如果不为null,说明要使用新的方式进行实例化,Spring容器也会使用这种方式进行实例化。
BeanPostProcessor
BeanPostProcessor是一个非常重要的Spring扩展接口。BeanPostProcessor用于在BeanFactory已经完成bean实例化之后,为其进一步做一些个性化的增强或装饰。Spring IoC容器通过实现此接口可以干很多事情,例如:bean的初始化和销毁操作、AOP动态代理操作等。
InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口。BeanPostProcessor包括14个方法,而InstantiationAwareBeanPostProcessor新增了两个方法,分别为:
- postProcessBeforeInstantiation(Class<?> beanClass, String beanName):在Spring IoC容器实例化Bean之前调用,可以返回一个BeanWrapper实例,如果返回null,表示要使用默认的方式创建Bean对象。
- postProcessAfterInstantiation(Object bean, String beanName):在Spring IoC容器实例化Bean之后调用。
InstantiationAwareBeanPostProcessor接口,是Spring IoC容器感知bean实例化过程的一个标志。如果容器中含有实现了InstantiationAwareBeanPostProcessor接口的bean,那么Spring IoC容器在创建Bean的时候,就会首先调用其实现的postProcessBeforeInstantiation方法。如果postProcessBeforeInstantiation方法返回了null,那么Spring IoC容器将会按照默认方式创建Bean。如果postProcessBeforeInstantiation方法没有返回null,那么Spring IoC容器将会使用返回的BeanWrapper来创建Bean对象。
总结
本文讲解了Spring容器如何使用BeanPostProcessor来确认构造方法。Spring容器会首先从BeanPostProcessorProvider中获取所有的实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor,如果找到了,则直接调用其postProcessBeforeInstantiation方法。这个方法可以对Bean的实例化操作进行拦截,其返回值如果为null,说明要使用默认方式进行实例化,如果不为null,说明要使用新的方式进行实例化,Spring容器也会使用这种方式进行实例化。