spring扩展 BeanDefinitionRegistryPostProcessor详解

简介

  • 首先引出一个问题,怎样的bean会被交给spring初始化?

一般而言Spring容器启动的过程中,解析配置文件 java config等等,会将Bean解析成Spring内部的BeanDefinition结构;试想一下如果我们能直接给spring BeanDefinition对象,这个bean交给spring去初始化。

  • 上面说的直接给spring BeanDefinition对象,这个bean交给spring去初始化的确可以这样做的。实现BeanDefinitionRegistryPostProcessor接口,自定义标签都可以实现一种更为灵活的注册bean对象;自定义标签的文章可以参考spring自定义标签;如果要注册bean可以参考AbstractBeanDefinitionParser.java中的registerBeanDefinition(holder, parserContext.getRegistry());其他的我就不过多赘述了。
  • mybatis MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口动态的注册mapper,我们使用起来才这么爽。

使用

  • 创建一个实体类对象RegistryBeanSample.java
package com.zzq.core.beaneefinitionregistrypostprocessor;

public class RegistryBeanSample {
	
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

  • 实现BeanDefinitionRegistryPostProcessor接口的类BeanDefinitionRegistryPostProcessorSample.java
package com.zzq.core.beaneefinitionregistrypostprocessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;

@Component
public class BeanDefinitionRegistryPostProcessorSample implements BeanDefinitionRegistryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		// GenericBeanDefinition是BeanDefinition其中一个实现
		GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
		// 设置初始化对象的类
		beanDefinition.setBeanClass(RegistryBeanSample.class);
		// 注册进spring ioc容器
		registry.registerBeanDefinition("registryBeanSample", beanDefinition);
	}

	
	
}

  • 因为BeanDefinitionRegistryPostProcessor是继承BeanFactoryPostProcessor后处理器的,所以要实现postProcessBeanFactory方法,这里的话我们关注点不在这儿,暂时忽略不管;
  • 调用registry.registerBeanDefinition("registryBeanSample", beanDefinition);会进入DefaultListableBeanFactory#registerBeanDefinition方法,把bean信息放到beanDefinitionMap中,spring会根据这些信息生成对应的对象。
  • 然后下一步就测试下spring容器中有没有这个bean,我用了ApplicationListener<ContextRefreshedEvent>启动完就会触发。
    在这里插入图片描述
  • 测试是成功的;当然在BeanDefinitionRegistryPostProcessorSample#postProcessBeanDefinitionRegistry方法中我只是简单的示例,并不够动态;像mybatis的MapperScannerConfigurer做的就比较动态了。

源码分析

  • 不管是spring项目、spring mvc或者spring boot项目都会进入AbstractApplicationContext#refresh方法,我们就从这个地方看起。BeanDefinitionRegistryPostProcessor接口源码,主要关注invokeBeanFactoryPostProcessors就可以了
public void refresh() throws BeansException, IllegalStateException {
	 .........省略..........
				// Invoke factory processors registered as beans in the context.
				// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
				invokeBeanFactoryPostProcessors(beanFactory);

	 ..........省略............
	}
  • invokeBeanFactoryPostProcessors方法源码
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<String>();
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
			List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
					new LinkedList<BeanDefinitionRegistryPostProcessor>();
			//getBeanFactoryPostProcessors()大部分情况下里面元素是空的,所以主要还是走下面beanFactory.getBeanNamesForType方法得到处理器
			for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryPostProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
					registryPostProcessors.add(registryPostProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}
			
			//目前看到mybatis框架  MapperScannerConfigurer实现BeanDefinitionRegistryPostProcessor接口  、spring的ConfigurationClassPostProcessor
			Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
					beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
			List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
					new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
			OrderComparator.sort(registryPostProcessorBeans);
			for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
				postProcessor.postProcessBeanDefinitionRegistry(registry);
			}
			invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
			processedBeans.addAll(beanMap.keySet());
		}
		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		//根据BeanFactoryPostProcessor接口得到它的实现类
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		//将BeanFactoryPostProcessor处理器分成几种来执行 priorityOrderedPostProcessors  orderedPostProcessorNames  nonOrderedPostProcessorNames
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
		List<String> orderedPostProcessorNames = new ArrayList<String>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			else if (isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		OrderComparator.sort(priorityOrderedPostProcessors);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		OrderComparator.sort(orderedPostProcessors);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		//最后,调用所有其他后处理器。
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
	
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
	}
  • 然后我们稍微debugbeanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);这段代码。
    在这里插入图片描述
  • 继续跟进DefaultListableBeanFactory#getBeanNamesForType方法
    在这里插入图片描述
  • 进入DefaultListableBeanFactory#doGetBeanNamesForType方法
  • 获取到所有已注册的BeanDefinition
    在这里插入图片描述
  • 匹配成功的会加入result
    在这里插入图片描述
  • 最后返回result
    在这里插入图片描述
  • 然后回过头来看DefaultListableBeanFactory#getBeansOfType方法;result会返回初始化好的bean
	public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException {

		String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
		Map<String, T> result = new LinkedHashMap<String, T>(beanNames.length);
		for (String beanName : beanNames) {
			try {
				//getBean(beanName, type) bean如果没有初始化 会在这儿初始化
				result.put(beanName, getBean(beanName, type));
			}
			catch (BeanCreationException ex) {
				Throwable rootCause = ex.getMostSpecificCause();
				if (rootCause instanceof BeanCurrentlyInCreationException) {
					BeanCreationException bce = (BeanCreationException) rootCause;
					if (isCurrentlyInCreation(bce.getBeanName())) {
						if (this.logger.isDebugEnabled()) {
							this.logger.debug("Ignoring match to currently created bean '" + beanName + "': " +
									ex.getMessage());
						}
						onSuppressedException(ex);
						// Ignore: indicates a circular reference when autowiring constructors.
						// We want to find matches other than the currently created bean itself.
						continue;
					}
				}
				throw ex;
			}
		}
		return result;
	}
  • 在回过来看看beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);的结果
    在这里插入图片描述
  • 下面看看它拿到这个beanMap干了什么?
  • 回调实现了BeanDefinitionRegistryPostProcessor接口的类,把registry传进去
    在这里插入图片描述
  • 下一步就会进我们自定义那个类了
    在这里插入图片描述
  • 最后就是注册一个BeanDefinition进去了;DefaultListableBeanFactory#registerBeanDefinition方法
    在这里插入图片描述
  • 这样我们自定义的bean就交给了spring了。本人水平有限,如果文章有误的地方,希望批评指正,感谢您的观看。

posted on 2020-04-25 09:58  愤怒的苹果ext  阅读(208)  评论(0编辑  收藏  举报

导航