BeanPostProcessor 就是Bean 的后置处理器 ,主要作用就是 Bean 实例之后,在 initialization 之前和之后 调用自定义的方法 改变一些属性
这里 的 initialization 包含: Bean 里面定义的 initMethod , InitializingBean 的 afterPropertiesSet
此外 还有一个 annotation @PostConstruct 和 @PreDestroy,也是可以对Bean 进行扩展的,但是他们的逻辑 和上面的 InitializingBean 和 自定义 的initMethod 的 底层一点点区别,他们 类似 BeanPostProcessor ,他对应的 类是 CommonAnnotationBeanPostProcessor
看一下 BeanPostProcessor 的接口
我用的 是 spring-beans: 5.1.7.RELEASE 版本,下面两个方法都加了 default
/**
主要作用就是 :允许对 Bean instances 自定义修改
ApplicationContexts 会自动 检查到 BeanPostProcessor beans 并将它们应用于随后创建的任何bean
*/
public interface BeanPostProcessor {
/**
* 在 进行调用 initialization 方法之前 先运行此方法,这里的 initialization 比如
* (InitializingBean's {@code afterPropertiesSet},或者 or 自定义的 init-method
* 默认是返回Bean 本身
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* 在 进行调用 initialization 方法之后 运行此方法, 这里的 initialization 比如
* (InitializingBean's {@code afterPropertiesSet},或者 or 自定义的 init-method
* 如果是 FactoryBean, 那么 此方法不仅作用于FactoryBean 实例,还作用于 此FactoryBean 创建的对象(自从 spring 2.0 ) ,此post-processor 通过 相应的check 可以决定是作用于 FactoryBean 还是 创建的对象,或者两者
* 默认是返回Bean 本身
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
@Configuration
public class BeanA {
private static final Logger log = LoggerFactory.getLogger(BeanA.class);
public BeanA() {
System.out.println("=======Bean A 构造函数======");
}
}
@Component
public class MysqlBeanPostProcessor implements BeanPostProcessor {
public MysqlBeanPostProcessor() {
System.out.println("=======run MysqlBeanPostProcessor 构造函数====");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof BeanA) {
// 这里我们可以对bean 做一下扩展
System.out.println("=====before Initialization 运行");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof BeanA) {
System.out.println("=====after Initialization 运行");
}
return bean;
}
}
@SpringBootApplication
public class ApplicationMain {
public static void main(String[] args) {
SpringApplication.run(ApplicationMain.class, args);
}
}
=======run MysqlBeanPostProcessor 构造函数====
INFO 3360 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
INFO 3360 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
INFO 3360 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.19]
INFO 3360 --- [ main] o.a.catalina.core.AprLifecycleListener : Loaded APR based Apache Tomcat Native library [1.2.23] using APR version [1.7.0].
INFO 3360 --- [ main] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
INFO 3360 --- [ main] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
INFO 3360 --- [ main] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1c 28 May 2019]
INFO 3360 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
INFO 3360 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1135 ms
=======Bean A 构造函数======
=====before Initialization 运行
=====after Initialization 运行
将上面的BeanA 方法 实现一下 InitializingBean
@Configuration
public class BeanA implements InitializingBean {
private static final Logger log = LoggerFactory.getLogger(BeanA.class);
public BeanA() {
System.out.println("=======Bean A 构造函数======");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("=======Bean A 运行 InitializingBean 的 afterPropertiesSet======");
}
}
运行结果:
=======run MysqlBeanPostProcessor 构造函数====
INFO 4200 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
INFO 4200 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
INFO 4200 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.19]
INFO 4200 --- [ main] o.a.catalina.core.AprLifecycleListener : Loaded APR based Apache Tomcat Native library [1.2.23] using APR version [1.7.0].
INFO 4200 --- [ main] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
INFO 4200 --- [ main] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
INFO 4200 --- [ main] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1c 28 May 2019]
INFO 4200 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
INFO 4200 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1093 ms
=======Bean A 构造函数======
=====before Initialization 运行
=======Bean A 运行 InitializingBean 的 afterPropertiesSet======
=====after Initialization 运行
修改 BeanA 代码如下:
@Configuration
public class BeanA implements InitializingBean {
private static final Logger log = LoggerFactory.getLogger(BeanA.class);
public BeanA() {
System.out.println("=======Bean A 构造函数======");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("=======Bean A 运行 InitializingBean 的 afterPropertiesSet======");
}
@PostConstruct
public void init(){
System.out.println("=======Bean A 运行 PostConstruct 的 初始化======");
}
}
运行结果如下:
说明 beforxxx 、 afterxxx、 方法是在 @PostConstruct 前后运行
=======run MysqlBeanPostProcessor 构造函数====
INFO 22072 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
INFO 22072 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
INFO 22072 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.19]
INFO 22072 --- [ main] o.a.catalina.core.AprLifecycleListener : Loaded APR based Apache Tomcat Native library [1.2.23] using APR version [1.7.0].
INFO 22072 --- [ main] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
INFO 22072 --- [ main] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
INFO 22072 --- [ main] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1c 28 May 2019]
INFO 22072 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
INFO 22072 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1325 ms
=======Bean A 构造函数======
=====before Initialization 运行
=======Bean A 运行 PostConstruct 的 初始化======
=======Bean A 运行 InitializingBean 的 afterPropertiesSet======
=====after Initialization 运行
接下来我们 看一下如何运行的,以及分析一下源码,在 打印日志的地方 打个断点,Debug 一下,如下图:
从下面我们可以看到
我们从上面的左下面的框框里面可以看到 这里是在 运行refresh() 里面方法时触发的,refresh这块后续整理一下//TODO,本次我们就从 AbstractAutowireCapableBeanFactory 类的 initializeBean 方法 开始解析
这里的流程也很清晰,大致为:
1.首先判断 是否设置了SecurityManagers ,如果设置了,就进行相关的权限配置 和 Aware 的扩展
2. 如果没有 直接进行 Aware 的扩展 ,Aware 这块就是 对相关的Bean 额外的配置一些响应的属性 ,代码块如下//TODO 后续整理一下
3. 判断bean 是不是应用程序自己定义的,如果不是 ,那就 遍历 运行 BeanPostProcessors 的postProcessBeforeInitialization 方法 这里有一个 getBeanPostProcessors() 方法,里面是获取所有的 实现了BeanPostProcessors 接口的类,这里是如果获取到的呢,在何时放进去的呢,下面会提到.
上面说到 的 注解 @PostConstruct 是在这一步运行的 ,相当于 BeanPostProcessors 的Beforxxxx 方法
4. 运行 invokeInitMethods ,这里有两种 ,一种是 继承了 InitializingBean ,那就实现 对应的afterPropertiesSet() 方法,或者是自定义的 InitMethod ,通过反射 去调用 上面的InitializingBean 和 自定义的initMethod 是在这一步运行
5. 判断bean 是不是应用程序自己定义的,如果不是 ,那就 遍历 运行 BeanPostProcessors 的postProcessAfterInitialization @PreDestory是在这一步 完成
// 这里就是对Bean 进行属性的配置
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
// 这里就是 遍历的去运行 BeanPostProcessors 的postProcessBeforeInitialization 方法
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
上面提到 getBeanPostProcessors()里面的值是何时放进去的,其实 是在 refresh() 方法里面的 registerBeanPostProcessors(beanFactory) 里面进行收集的.
支付宝 | 微信 |
---|---|
如果有帮助记得打赏哦 | 特别需要您的打赏哦 |