转自: https://www.jianshu.com/p/d26e8ec9c077?
BeanPostProcessor
也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor
中定义的两个方法。BeanPostProcessor
的源码如下
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
其中postProcessBeforeInitialization
方法会在每一个bean对象的初始化方法调用之前回调;postProcessAfterInitialization
方法会在每个bean对象的初始化方法调用之后被回调。具体执行时期可以参考Spring中Bean的生命周期源码探究。
自定义BeanPostProcessor
查看BeanPostProcessor源码,可以看到它两个方法的参数都相同,其中第一个参数Object bean
表示当前正在初始化的bean对象。此外两个方法都返回Object类型的实例,返回值既可以是将入参Object bean
原封不动的返回出去,也可以对当前bean进行包装再返回。来看看下面的自定义BeanPostProcessor
/**
* 后置处理器:初始化前后进行处理工作
* 需要将后置处理器加入到容器中
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization..."+beanName+"..."+bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization..."+beanName+"..."+bean); return bean; } }
Spring容器中加入MyBeanPostProcessor
之后,针对容器中每个创建的Bean对象(Spring自身创建的Bean和应用程序创建的Bean),都会回调postProcessBeforeInitialization
和postProcessAfterInitialization
方法。
执行原理
BeanPostProcessor的执行是定义在容器的刷新过程中,容器刷新对象具体的方法为:AbstractApplicationContext.refresh()
。
在refresh方法执行的调用栈中会去调用AbstractAutowireCapableBeanFactory.doCreateBean()
方法,该方法节选源码如下
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } invokeInitMethods(beanName, wrappedBean, mbd); if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
看到在调用初始化方法前后会分别调用applyBeanPostProcessorsBeforeInitialization()
和applyBeanPostProcessorsAfterInitialization()
。applyBeanPostProcessorsBeforeInitialization()
方法的源码如下
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; //获取所有的BeanPostProcessor进行遍历 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
可以看到其逻辑为遍历得到容器中所有的BeanPostProcessor
,然后一次执行postProcessBeforeInitialization
,一但返回null,就跳出for循环不执行后面的BeanPostProcessor.postProcessorsBeforeInitialization()
。也就是说如果返回的是null那么我们通过getBean方法将得不到目标Bean。applyBeanPostProcessorsBeforeInitialization()
方法的逻辑和上面一致,就是将循环执行的beanProcessor.postProcessBeforeInitialization()
替换成beanProcessor.postProcessAfterInitialization()
Spring底层的很多功能特性都是借助BeanPostProcessor
的子类来实现。
常见BeanPostProcessor分析
下图是debug过程中,ApplicationContext对象中的包含的BeanPostProcessor。具体包含哪些BeanPostProcessor和具体应用程序相关,除了下标3中的MyBeanPostProcessor为自定义的BeanPostProcessor,其余均为Spring自带的BeanPostProcessor。
下面来分析一下ApplicationContextAwareProcessor
和AutowiredAnnotationProcessor
的执行原理。
ApplicationContextAwareProcessor
ApplicationContextAwareProcessor
后置处理器的作用是,当应用程序定义的Bean实现ApplicationContextAware
接口时注入ApplicationContext
对象。
@Component
public class Car implements ApplicationContextAware { private ApplicationContext applicationContext; public Car(){ System.out.println("car instance..."); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("ApplicationContextAware...setApplicationContext()"); this.applicationContext = applicationContext; } }
那Car是如何通过实现ApplicationContextAware
接口就能获得ApplicationContext
对象呢?答案是通过ApplicationContextAwareProcessor
后置处理器来实现,我们来看看ApplicationContextAwareProcessor
的源码
class ApplicationContextAwareProcessor implements BeanPostProcessor { private final ConfigurableApplicationContext applicationContext; private final StringValueResolver embeddedValueResolver; /** * Create a new ApplicationContextAwareProcessor for the given context. */ public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory()); } @Override public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; // 这里bean是Car,它实现了ApplicationContextAware接口 if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { invokeAwareInterfaces(bean); } return bean; } private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { // 会执行这里回调car重写的setApplicationContext方法,然后将this.applicationContext注入给Car ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } }
InitDestroyAnnotationBeanPostProcessor
InitDestroyAnnotationBeanPostProcessor
后置处理器是用来处理自定义的初始化方法和销毁方法。Spring中提供了3种自定义初始化和销毁方法:
- 通过@Bean指定init-method和destroy-method属性
- Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);
- @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法@PreDestroy:在容器销毁bean之前通知我们进行清理工作
InitDestroyAnnotationBeanPostProcessor
的作用就是让第3种方式生效。先看看如何使用@PostConstruct
和@PreDestroy
注解。
@Component
public class Car { public Car(){ System.out.println("car instance..."); } /** * 自定义的初始化方法 */ @PostConstruct public void init(){ System.out.println("car ... init..."); } /** * 自定义的销毁方法 */ @PreDestroy public void detory(){ System.out.println("car ... detory..."); } }
InitDestroyAnnotationBeanPostProcessor
会在Bean创建的时候通过反射的方式查找包含@PostConstruct
和@PreDestroy
注解的方法,然后再通过反射执行方法。我们来看看InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()
的源码
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 获取bean的metadata LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { // 执行@PostConstruct指定的init方法 metadata.invokeInitMethods(bean, beanName); } catch (InvocationTargetException ex) { throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Failed to invoke init method", ex); } return bean; }
metadata中已经解析出initMethods和destroyMethods,其具体内容如下。
metadata.invokeInitMethods(bean, beanName);
就是根据反射执行init方法。
InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor
是BeanPostProcessor
的子接口。
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { //实例化Bean之前调用 Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException; //实例化Bean之后调用 boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException; //设置Bean对象中的某个属性时调用 PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException; }
这两个接口的功能基本类似,不过要注意InstantiationAwareBeanPostProcessor
和BeanPostProcessor
的方法名区别。InstantiationAwareBeanPostProcessor
中是Instantiation, 而BeanPostProcessor
是Initialization。