spring源码:注册BeanPostProcessor

一、介绍

  BeanPostProcessor接口定义了回调方法,开发者可以实现这些回调方法来提供自定义的实例化逻辑、依赖项解析逻辑等等。BeanPostProcessor也叫Bean后处理器Spring框架会加载Bean过程中特定的步骤,来调用Bean后处理器中的接口方法,并传入一些值给这些回调方法。具体可参考:spring中常用的BeanPostProcessorSpring官方文档介绍

二、BeanPostProcessor存在哪儿?

  本篇文章重点不在于哪些地方回调了这些方法,而是要介绍这些BeanPostProcessor何时注册到容器中的。我们首先看下BeanPostProcessor存在容器的哪个地方,从回调接口方法的地方找起。回调方法有很多处,我们挑一处初始化bean前的回调源码:

	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		// 1. 调用Aware方法
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 2. 回调Bean后处理器的postProcessBeforeInitialization
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 3. 调用bean的初始化方法
			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()) {
			// 4. 回调Bean后处理器的postProcessAfterInitialization方法
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

该代码片段来自于AbstractAutowireCapableBeanFactory类的initializeBean方法,可以看到第2步和第4步都调用了BeanPostProcessor的接口方法,我们点进去看看第2个步骤中的代码

	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		// 循环容器中所有的BeanPostProcessor
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			// 调用BeanPostProcessor的postProcessBeforeInitialization方法
			Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

调用BeanPostProcessor的哪个方法我们不关心,我们只关心容器中的BeanPostProcessor从哪儿来的,继续看下getBeanPostProcessors()这个方法:

	/** BeanPostProcessors to apply in createBean */
	private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
		
	public List<BeanPostProcessor> getBeanPostProcessors() {
		return this.beanPostProcessors;
	}

这段代码在AbstractBeanFactory类中,所以容器中所有的BeanPostProcessor都存在AbstractBeanFactory类中的beanPostProcessors属性里。

三、注册BeanPostProcessor源码

  从上面我们看到了,容器中的BeanPostProcessor都存在AbstractBeanFactory类中的beanPostProcessors属性中。那么是何时注册进去的呢?顺序有是怎样的呢

1. 初始化容器的代码

来看下ApplicationContext初始化(也叫刷新Application上下文)的经典代码:

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 1. 准备刷新的上下文环境
			prepareRefresh();

			// 2. 初始化BeanFactory,并进行XML文件的加载
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 3. 对BeanFactory进行各种功能填充
			prepareBeanFactory(beanFactory);

			try {
				// 4. 子类覆盖犯法做额外的处理
				postProcessBeanFactory(beanFactory);

				// 5. 调用BeanFactory后处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// 6. 注册bean后处理器,在调用getBean的时候回调这些bean后处理器的方法
				registerBeanPostProcessors(beanFactory);

				// 7. 为上下文初始化Message源
				initMessageSource();

				// 8. 初始化应用消息广播器,并放入ApplicationEventMulticaster中
				initApplicationEventMulticaster();

				// 9. 留给子类初始化其他bean
				onRefresh();

				// 10. 注册监听器
				registerListeners();

				// 11. 初始化剩下的单例Bean(非惰性的)
				finishBeanFactoryInitialization(beanFactory);

				// 12. 最后一步,发布通知事件
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// 销毁已经创建的单例,以避免挂起资源。
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

该代码来自AbstractApplicationContext类的refresh方法,是ApplicationContext初始化的入口。整个Spring框架加载的过程就是这个方法中,可以好好看一下。

很显然跟BeanPostProcessor注册相关的就是第6步,点进去看下

2. 注册BeanPostProcessor
	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}

转发到了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法,点进去看下:

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		// 获取所有BeanPostProcessor类型的beanName
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// 1. 注册一个BeanPostProcessorChecker
		// 当一个bean在BeanPostProcessor实例化过程中被创建时,
		// 也就是当一个bean没有资格被所有BeanPostProcessor处理时,它会输出一条日志。
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// 2. 给BeanPostProcessor分类:实现了PriorityOrdered、Ordered接口和其他普通BeanPostProcessor
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			// 2.1 初始化实现PriorityOrdered接口的BeanPostProcessor
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				// 2.1.1 如果是MergedBeanDefinitionPostProcessor类型,记录到internalPostProcessors
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			// 2.2 记录实现Ordered接口的Bean后处理器名称
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			// 2.3 记录其他Bean后处理器名称
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// 3. 注册BeanPostProcessor
		// 3.1 注册实现PriorityOrdered接口的BeanPostProcessors
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// 3.2 注册实现Ordered接口的BeanPostProcessors
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String ppName : orderedPostProcessorNames) {
			// 根据beanName从容器中获取bean
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// 3.3 注册剩下的BeanPostProcessors
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// 4. 注册MergedBeanDefinitionPostProcessor类型的Bean后处理器
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// 5. 最后在注册一个ApplicationListenerDetector类型的Bean后处理器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

从上面代码我们可以看到,此逻辑注册了6种BeanPostProcessor,它们的顺序如下:

  1. BeanPostProcessorChecker
    作用:当某些非BeanPostProcessor的Bean实例,在BeanPostProcessor实例化过程中被创建时输出一条日志。
  2. 实现PriorityOrdered接口的BeanPostProcessor
  3. 实现Ordered接口的BeanPostProcessor
  4. 其他BeanPostProcessor
  5. 实现PriorityOrdered接口且类型为MergedBeanDefinitionPostProcessorBean
    这个都可以当面试题了,是否所有实现了PriorityOrdered接口的BeanPostProcessor的优先级,都比实现Ordered接口的BeanPostProcessor优先级高?
  6. ApplicationListenerDetector
    作用:记录容器中监听器的beanName

读者看完以上代码可能会存在以下两个问题:

  • BeanPostProcessor是否重复注册了?
    代码如下:
// 2.1 初始化实现PriorityOrdered接口的BeanPostProcessor
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
	BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
	priorityOrderedPostProcessors.add(pp);
	// 2.1.1 如果是MergedBeanDefinitionPostProcessor类型,记录到internalPostProcessors
	if (pp instanceof MergedBeanDefinitionPostProcessor) {
		internalPostProcessors.add(pp);
	}
}
// 省略其他无关代码... 
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

有些BeanPostProcessor添加到priorityOrderedPostProcessors和internalPostProcessors中,是否重复注册了呢?继续看下注册代码就明白了:

	public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
		// 先移除
		this.beanPostProcessors.remove(beanPostProcessor);
		// 再添加
		this.beanPostProcessors.add(beanPostProcessor);
		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
			this.hasInstantiationAwareBeanPostProcessors = true;
		}
		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
			this.hasDestructionAwareBeanPostProcessors = true;
		}
	}

注册之前,会把原来的BeanPostProcessor给移除掉,所以不会重复注册。

  • 为什么初始化实现PriorityOrdered接口的BeanPostProcessor时,不初始化其他BeanPostProcessor?
    在获取实现PriorityOrdered接口的BeanPostProcessor时,是使用beanFactory.getBean(ppName, BeanPostProcessor.class)直接初始化Bean的;而获取其他的BeanPostProcessor时,是使用orderedPostProcessorNames.add(ppName),仅保存了BeanPostProcessor的bean名称,放到后面初始化的。为什么不一起使用beanFactory的getBean方法加载bean呢?应该是因为注册完优先级高的BeanPostProcessor后,再加载优先级低的BeanPostProcessor,此时已注册完的BeanPostProcessor就能起作用了

四、 其他注册位置

  BeanPostProcessor最主要的注册逻辑,在上面讲解的AbstractApplicationContext类的registerBeanPostProcessors方法中。但是这个方法不是唯一的注册逻辑,除此之外还有其他Spring内部硬编码注册的地方。

所谓的注册就是把创建的BeanPostProcessor保存在AbstractBeanFactory类中的beanPostProcessors属性中。

1. 刷新Application上下文

在上面刷新Application上下文代码中的第3步,AbstractApplicationContext类的prepareBeanFactory方法中也有注册BeanPostProcessor的一些代码,注册的都是Spring内置的Bean后处理器。

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// 1. 注册Bean后处理器:ApplicationContextAwareProcessor
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);

		// 省略无关代码...

		// 2. 注册Bean后处理器:ApplicationListenerDetector
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			// 3. 注册Bean后处理器:LoadTimeWeaverAwareProcessor
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// 省略无关代码...
	}

有三处注册了Bean后处理器

2. ConfigurationClassPostProcessor

ConfigurationClassPostProcessor是一个BeanFactory后处理器,在注册BeanPostProcessor的主逻辑前,会调用BeanFactory后处理器的postProcessBeanFactory方法,那么我们来看下ConfigurationClassPostProcessor类的postProcessBeanFactory方法代码:

	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		int factoryId = System.identityHashCode(beanFactory);
		if (this.factoriesPostProcessed.contains(factoryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + beanFactory);
		}
		this.factoriesPostProcessed.add(factoryId);
		if (!this.registriesPostProcessed.contains(factoryId)) {
			// BeanDefinitionRegistryPostProcessor hook apparently not supported...
			// Simply call processConfigurationClasses lazily at this point then.
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}

		enhanceConfigurationClasses(beanFactory);
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}

五、借鉴Spring内部用法

  • 根据类型获取容器中的bean名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
  • 判断beanName对应的类型是否匹配
// ppName的bean是否是PriorityOrdered类型
boolean match = beanFactory.isTypeMatch(ppName, PriorityOrdered.class);
  • 根据beanName和类型从容器中获取bean实例
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值