spring--bean后置处理器(BeanPostProcessor)原理解析

功能描述:

  • 实现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;
    	}
    
    }
    

如何使用:

  1. 定义要处理的接口类型

    public interface TestBeanPostProcessorInterface {
    
        String getPassword();
    
        void setPassword(String password);
    }
    
  2. 添加实际需要处理的类

    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;
        }
    }
    
  3. 定义后置处理器

    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;
        }
    }
    
    
  4. 编写测试类

    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());
        }
    }
    
    
  5. 执行日志

    我们看到 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过程中,从抽象类AbstractApplicationContextrefresh方法开始,去除注释和日志,我们来看看源码
    @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));
    }
    

    注册过程还是比较简单的,我们看到,在注册过程中还创建了两个后置处理器BeanPostProcessorCheckerApplicationListenerDetector,这个在后面分析作用
    后置处理器的注册已经完成了,接下来我们看一下他的调用过程

后置处理器的调用

  1. 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接口的类

  1. 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)”);

  2. 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();
    	}
    }
    
  1. 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);
    		}
    	}
    
    }
    
  1. AutowiredAnnotationBeanPostProcessor 增加对Autowired注解的支持

  2. CommonAnnotationBeanPostProcessor 负责解析@Resource、@WebServiceRef、@EJB注解

  3. ConfigurationClassPostProcessor 负责解析@Configuration、@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean注解

  4. 还有很多。。。

总结

  1. 可实现PriorityOrdered或Ordered接口定义后置处理器执行顺序
  2. 后置处理器A存在依赖bean的情况下,这个bean将无法被A及优先级低于A的处理器处理
  3. @Bean、@ComponentScan、@Import、@Resource等实用注解是通过后置处理器处理的
  4. bean初始化时先进行BeanNameAware、BeanClassLoaderAware和BeanFactoryAware感知注入,再执行前置处理,然后对实现了InitializingBean接口的方法afterPropertiesSet进行初始化,最后执行后置处理
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值