文章目录
- 功能描述:
- 如何使用:
- 后置处理器加载解析
- 后置处理器的调用
- 举例谈谈spring内部实现了BeanPostProcessor接口的类
- BeanPostProcessorChecker用于检查是否存在不会被所有后置处理器处理的bean
- ApplicationListenerDetector用于管理监听器
- ApplicationContextAwareProcessor用于实现感知
- AutowiredAnnotationBeanPostProcessor 增加对Autowired注解的支持
- CommonAnnotationBeanPostProcessor 负责解析@Resource、@WebServiceRef、@EJB注解
- ConfigurationClassPostProcessor 负责解析@Configuration、@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean注解
- 总结
功能描述:
-
实现BeanPostProcessor接口允许我们可以对所有bean在创建之前和之后做一些自己的处理
-
BeanPostProcessor 接口定义:
public interface BeanPostProcessor { /** * 前置处理,实例化bean之前对bean进行处理 */ @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } /** * 后置处理,实例化bean之后对bean进行处理 */ @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
如何使用:
-
定义要处理的接口类型
public interface TestBeanPostProcessorInterface { String getPassword(); void setPassword(String password); }
-
添加实际需要处理的类
import org.springframework.stereotype.Component; @Component public class UserInfoVO implements TestBeanPostProcessorInterface { private String password = "password"; @Override public String getPassword() { return password; } @Override public void setPassword(String password) { this.password = password; } }
-
定义后置处理器
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class BeanPostProcessorConfig implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 这是判断只对我们感兴趣的接口做处理 if (bean instanceof TestBeanPostProcessorInterface) { // 打印处理前password的值 String password = ((TestBeanPostProcessorInterface) bean).getPassword(); System.out.println(String.format("handler beanName: %s, password: %s", beanName, password)); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // 这是判断只对我们感兴趣的接口做处理 if (bean instanceof TestBeanPostProcessorInterface) { // 重新设置password的值 ((TestBeanPostProcessorInterface) bean).setPassword("********"); } return bean; } }
-
编写测试类
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class BeanPostProcessorTest { @Autowired private UserInfoVO userInfoVO; @Test public void test() { System.out.println(userInfoVO.getPassword()); } }
-
执行日志
我们看到 userInfoVO类的password 参数被替换成了********
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.0.RELEASE) 2020-06-01 13:43:24.952 INFO 11432 --- [ main] c.e.d.c.spring.BeanPostProcessorTest : Starting BeanPostProcessorTest on PC with PID 11432 (started by ASUS in E:\workspace\demo) 2020-06-01 13:43:24.954 INFO 11432 --- [ main] c.e.d.c.spring.BeanPostProcessorTest : No active profile set, falling back to default profiles: default 2020-06-01 13:43:25.708 INFO 11432 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode! 2020-06-01 13:43:25.711 INFO 11432 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode. 2020-06-01 13:43:25.783 INFO 11432 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 46ms. Found 0 repository interfaces. handler beanName : userInfoVO, password : password 2020-06-01 13:43:27.063 INFO 11432 --- [ main] c.e.d.c.spring.BeanPostProcessorTest : Started BeanPostProcessorTest in 2.857 seconds (JVM running for 4.225) ******** Process finished with exit code 0
后置处理器加载解析
- 这个是在创建applicationContext过程中,从抽象类AbstractApplicationContext的refresh方法开始,去除注释和日志,我们来看看源码
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); // 注册后置处理器 registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }
这里我们只关心registerBeanPostProcessors方法
registerBeanPostProcessors注册拦截bean创建的后置处理器
-
源码
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); } public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { // 获取所有实现了BeanPostProcessor接口的beanName String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // 计算一个bean最终应该会被实现了BeanPostProcessor接口处理的数量 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; // 添加一个后置处理器,放在后面说明 beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // 保存实现了优先排序接口(PriorityOrdered)的类 List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); // 保存实现了MergedBeanDefinitionPostProcessor接口的类,可以理解为spring内部类 List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); // 保存实现了排序接口(Ordered)的类 List<String> orderedPostProcessorNames = new ArrayList<>(); // 保存未实现任何排序接口的类 List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { // 判断是否实现了PriorityOrdered接口 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 获取并实例化bean BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); // 可以理解为判断是否spring框架内部使用的实现类 if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } // 判断是否实现了Ordered接口 else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } // 未实现排序接口的保存到nonOrderedPostProcessorNames集合 else { nonOrderedPostProcessorNames.add(ppName); } } // 进行排序后优先注册 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // 处理实现了Ordered排序接口的BeanPostProcessors实现类 List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); // 可以理解为判断是否框架内部使用的实现类 if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } // 进行排序后优先注册 sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // 处理无排序的BeanPostProcessors实现类 List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); // 可以理解为判断是否spring框架内部使用的实现类 if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } // 无排序直接注册 registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // 对内部类的排序 sortPostProcessors(internalPostProcessors, beanFactory); // 重新注册内部类,作用是将内部类的注册放到最后 registerBeanPostProcessors(beanFactory, internalPostProcessors); // 添加一个后置处理器,放在后面说明 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
注册过程还是比较简单的,我们看到,在注册过程中还创建了两个后置处理器BeanPostProcessorChecker和ApplicationListenerDetector,这个在后面分析作用
后置处理器的注册已经完成了,接下来我们看一下他的调用过程
后置处理器的调用
-
bean实例化前、后的处理调用过程
跳过bean实例化过程,直接看一下初始化bean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { // 判断是否启用了java安全管理器,正常情况下是null的,除非手动设置打开安全管理器 if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 进行BeanNameAware、BeanClassLoaderAware和BeanFactoryAware感知注入 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; // 判断是否合成bean,默认 synthetic = false,则!mbd.isSynthetic() = true if (mbd == null || !mbd.isSynthetic()) { // 调用前置处理器 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 如果实现了InitializingBean接口,则调用afterPropertiesSet方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 调用后置处理器 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
@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; } @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; // 遍历处理器 for (BeanPostProcessor processor : getBeanPostProcessors()) { // 执行后置处理器 Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
举例谈谈spring内部实现了BeanPostProcessor接口的类
-
BeanPostProcessorChecker用于检查是否存在不会被所有后置处理器处理的bean
什么情况下会出现这个问题呢,首先我们要知道两件事情,然后看一下注册流程图
1、单例bean只会实例化一次
2、bean实例化的前后都会被后置处理器处理
流程图:
综上我们可以看到在实例化后置处理器时会去实例化他的依赖bean,实例化依赖bean时又会执行后置处理器,但是此时的后置处理器并没有全部注册完成,所以这个依赖bean不会被还没实例化的后置处理器处理到我们看看spring是怎么实现BeanPostProcessorChecker的
private static final class BeanPostProcessorChecker implements BeanPostProcessor { private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class); private final ConfigurableListableBeanFactory beanFactory; private final int beanPostProcessorTargetCount; public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) { this.beanFactory = beanFactory; this.beanPostProcessorTargetCount = beanPostProcessorTargetCount; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { // 1、bean不是后置处理器,2、不是内部bean,3、此时注册的后置处理器小于计算的总后置处理器 if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) && this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) { // 打印日志 if (logger.isInfoEnabled()) { logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() + "] is not eligible for getting processed by all BeanPostProcessors " + "(for example: not eligible for auto-proxying)"); } } return bean; } private boolean isInfrastructureBean(@Nullable String beanName) { if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) { BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName); // RootBeanDefinition.ROLE_INFRASTRUCTURE = 2,标记为完全内部使用的bean return (bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE); } return false; } }
如果存在这种情况则会打印一行日志
logger.info(“Bean '” + beanName + “’ of type [” + bean.getClass().getName() +
"] is not eligible for getting processed by all BeanPostProcessors " +
“(for example: not eligible for auto-proxying)”); -
ApplicationListenerDetector用于管理监听器
ApplicationListenerDetector主要做两件事
1、bean实例化时如果这个bean是监听器且是单例模式的则在广播中注册这个监听器
2、bean销毁时判断如果是监听器则在广播中移除这个监听器
-
附上源码
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor { private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class); private final transient AbstractApplicationContext applicationContext; private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256); public ApplicationListenerDetector(AbstractApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { this.singletonNames.put(beanName, beanDefinition.isSingleton()); } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof ApplicationListener) { // potentially not detected as a listener by getBeanNamesForType retrieval Boolean flag = this.singletonNames.get(beanName); if (Boolean.TRUE.equals(flag)) { // singleton bean (top-level or inner): register on the fly this.applicationContext.addApplicationListener((ApplicationListener<?>) bean); } else if (Boolean.FALSE.equals(flag)) { if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) { // inner bean with other scope - can't reliably process events logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " + "but is not reachable for event multicasting by its containing ApplicationContext " + "because it does not have singleton scope. Only top-level listener beans are allowed " + "to be of non-singleton scope."); } this.singletonNames.remove(beanName); } } return bean; } @Override public void postProcessBeforeDestruction(Object bean, String beanName) { if (bean instanceof ApplicationListener) { try { ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster(); multicaster.removeApplicationListener((ApplicationListener<?>) bean); multicaster.removeApplicationListenerBean(beanName); } catch (IllegalStateException ex) { // ApplicationEventMulticaster not initialized yet - no need to remove a listener } } } @Override public boolean requiresDestruction(Object bean) { return (bean instanceof ApplicationListener); } @Override public boolean equals(@Nullable Object other) { return (this == other || (other instanceof ApplicationListenerDetector && this.applicationContext == ((ApplicationListenerDetector) other).applicationContext)); } @Override public int hashCode() { return ObjectUtils.nullSafeHashCode(this.applicationContext); } }
-
注意在移除监听器时会清空整个监听器缓存
@Override public void removeApplicationListener(ApplicationListener<?> listener) { synchronized (this.retrievalMutex) { this.defaultRetriever.applicationListeners.remove(listener); // 清空监听器缓存 this.retrieverCache.clear(); } } @Override public void removeApplicationListenerBean(String listenerBeanName) { synchronized (this.retrievalMutex) { this.defaultRetriever.applicationListenerBeans.remove(listenerBeanName); // 清空监听器缓存 this.retrieverCache.clear(); } }
-
ApplicationContextAwareProcessor用于实现感知
该后置处理器会对实现了EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware接口的bean注入对应的实例
- 源码很简单
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 @Nullable public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 判断这个bean是否实现了这些接口 if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){ return bean; } AccessControlContext acc = null; if (System.getSecurityManager() != null) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { invokeAwareInterfaces(bean); } return bean; } // 注入响应的实例 private void invokeAwareInterfaces(Object bean) { 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) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }
-
AutowiredAnnotationBeanPostProcessor 增加对Autowired注解的支持
-
CommonAnnotationBeanPostProcessor 负责解析@Resource、@WebServiceRef、@EJB注解
-
ConfigurationClassPostProcessor 负责解析@Configuration、@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean注解
-
还有很多。。。
总结
- 可实现PriorityOrdered或Ordered接口定义后置处理器执行顺序
- 后置处理器A存在依赖bean的情况下,这个bean将无法被A及优先级低于A的处理器处理
- @Bean、@ComponentScan、@Import、@Resource等实用注解是通过后置处理器处理的
- bean初始化时先进行BeanNameAware、BeanClassLoaderAware和BeanFactoryAware感知注入,再执行前置处理,然后对实现了InitializingBean接口的方法afterPropertiesSet进行初始化,最后执行后置处理