文章目录
结论先行
通过实现BeanPostProcessor接口,并实现postProcessBeforeInitialization和postProcessAfterInitialization方法,可以自定义bean初始化前后的逻辑
BeanPostProcessor实现类定义
package com.ouyangxizhu.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* 后置处理器:初始化前后进行处理工作
* 将后置处理器加入到容器中
*
* @author lfy
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessBeforeInitialization..." + beanName + "=>" + bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessAfterInitialization..." + beanName + "=>" + bean);
return bean;
}
}
配置类
package com.ouyangxizhu.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.ouyangxizhu.bean")
public class MainConfigBeanPostProcessor {
}
启动类
package com.ouyangxizhu;
import com.ouyangxizhu.config.MainConfigBeanPostProcessor;
import com.ouyangxizhu.config.MainConfigInitializingBeanDisposableBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTestBeanPostProcessor {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigBeanPostProcessor.class);
context.close();
}
}
结果
八月 04, 2020 10:42:56 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0: startup date [Tue Aug 04 22:42:56 CST 2020]; root of context hierarchy
postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerProcessor=>org.springframework.context.event.EventListenerMethodProcessor@149494d8
postProcessAfterInitialization...org.springframework.context.event.internalEventListenerProcessor=>org.springframework.context.event.EventListenerMethodProcessor@149494d8
postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerFactory=>org.springframework.context.event.DefaultEventListenerFactory@646007f4
postProcessAfterInitialization...org.springframework.context.event.internalEventListenerFactory=>org.springframework.context.event.DefaultEventListenerFactory@646007f4
postProcessBeforeInitialization...mainConfigBeanPostProcessor=>com.ouyangxizhu.config.MainConfigBeanPostProcessor$$EnhancerBySpringCGLIB$$b41bc1c4@481a15ff
postProcessAfterInitialization...mainConfigBeanPostProcessor=>com.ouyangxizhu.config.MainConfigBeanPostProcessor$$EnhancerBySpringCGLIB$$b41bc1c4@481a15ff
cat..............constructor
postProcessBeforeInitialization...cat=>com.ouyangxizhu.bean.Cat@545997b1
cat...............init
postProcessAfterInitialization...cat=>com.ouyangxizhu.bean.Cat@545997b1
八月 04, 2020 10:42:57 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0: startup date [Tue Aug 04 22:42:56 CST 2020]; root of context hierarchy
cat..............destroy
Process finished with exit code 0
原理
1.在postProcessBeforeInitialization和postProcessAfterInitialization方法前面分别打一个断点,以debug方式运行启动类
2.进入到postProcessBeforeInitialization方法中,在左下角可以查看调用栈,调用栈如下,如果没有这么详细,可以点击图中右上角的按钮(下面内容自己debug看)
org.springframework.context.annotation.AnnotationConfigApplicationContext
org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
org.springframework.beans.factory.ObjectFactory#getObject
org.springframework.beans.factory.support.AbstractBeanFactory#createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
3. 原理
遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization,
一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization
BeanPostProcessor原理
populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值
initializeBean
{
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
BeanValidationPostProcessor
给javaBean复制以后做校验工作,执行org.springframework.validation.beanvalidation.BeanValidationPostProcessor#doValidate这个方法做校验
InitDestroyAnnotationBeanPostProcessor
处理@PostConstruct和@PreDestroy注解
这个可以在相应的初始化方法打一个断点,debug运行进到断点之后看调用栈
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//生命周期注解信息
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
//调用初始化方法
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;
}
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> initMethodsToIterate =
(this.checkedInitMethods != null ? this.checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (LifecycleElement element : initMethodsToIterate) {
if (debug) {
logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
//反射调用初始化方法
element.invoke(target);
}
}
}
AutowiredAnnotationBeanPostProcessor
处理@Autowired注解