BeanPostProcessor 后置处理器
在 bean 初始化前后做处理,对 bean 初始化方法做了拦截,使用也很简单,新建一个组件实现 BeanPostProcessor 并加入到容器中.
BeanPostProcessor 提供了两个方法,实现这两个方法即可:
- postProcessBeforeInitialization: 在初始化之前调用
- postProcessAfterInitialization: 在初始化之后调用
实现一个 BeanPostProcessor 后置处理器
package com.demon.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* BeanPostProcessor后置处理器实现
*
* @author Demon-HY
* @date 2019-12-10
*/
// 将后置处理器加入到容器中
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
System.out.println("MyBeanPostProcessor 初始化方法");
}
// 可以设置bean的值
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之前调用, beanName=" + beanName + " bean=" +bean.getClass());
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化之后调用, beanName=" + beanName + " bean=" +bean.getClass());
return bean;
}
}
执行测试用例
@Test
public void test2() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
System.out.println("容器创建成功.................");
// 关闭容器
context.close();
}
打印输出:
MyBeanPostProcessor 初始化方法
初始化之前调用, beanName=org.springframework.context.event.internalEventListenerProcessor bean=class org.springframework.context.event.EventListenerMethodProcessor
初始化之后调用, beanName=org.springframework.context.event.internalEventListenerProcessor bean=class org.springframework.context.event.EventListenerMethodProcessor
初始化之前调用, beanName=org.springframework.context.event.internalEventListenerFactory bean=class org.springframework.context.event.DefaultEventListenerFactory
初始化之后调用, beanName=org.springframework.context.event.internalEventListenerFactory bean=class org.springframework.context.event.DefaultEventListenerFactory
初始化之前调用, beanName=config bean=class com.demon.config.Config$$EnhancerBySpringCGLIB$$869d37c8
初始化之后调用, beanName=config bean=class com.demon.config.Config$$EnhancerBySpringCGLIB$$869d37c8
初始化之前调用, beanName=color bean=class com.demon.bean.Color
初始化之后调用, beanName=color bean=class com.demon.bean.Color
容器创建成功.................
BeanPostProcessor 原理
在我们实现的 MyBeanPostProcessor 的 postProcessBeforeInitialization()方法里面打断点debug,可以看到下面的代码,Spring 在 AbstractAutowireCapableBeanFactory 类里面
预留了 BeanPostProcessor 处理器的插槽.
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 在 bean 初始化之前调用
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
// 实际执行 bean 的初始化方法
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
// 在 bean 初始化之后调用
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) 代码实现:
// 遍历容器中所有的 BeanPostProcessor,并挨个调用,当某一个 BeanPostProcessor.postProcessBeforeInitialization() 方法返回false,则跳出该方法
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
BeanPostProcessor 典型应用 ApplicationContextAwareProcessor
ApplicationContextAwareProcessor 接口就是基于 BeanPostProcessor 实现的,当你的Service需要注入ApplicationContext时,只需要实现ApplicationContextAware 接口,
就可以实现 ApplicationContext 的注入.
先看下demo:
package com.demon.service;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
/**
* @author Demon-HY
* @date 2019-12-12
*/
@Service
public class UserService implements ApplicationContextAware {
// Spring 容器
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
}
找到实现了 BeanPostProcessor 接口的 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;
// 如果
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
// 设置属性
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
// bean 实现了 EnvironmentAware 接口,则调用 bean.setEnvironment() 设置系统环境
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);
}
// bean 实现了 ApplicationContextAware 接口,则调用 bean.setApplicationContext() 设置Spring 容器
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
}
咖啡小馆
QQ群: 823971061 点击按钮入群