Spring核心扩展点BeanDefinitionRegistryPostProcessor源码分析

编程入门 行业动态 更新时间:2024-10-28 19:32:03

Spring核心扩展点BeanDefinitionRegistryPostProcessor<a href=https://www.elefans.com/category/jswz/34/1770099.html style=源码分析"/>

Spring核心扩展点BeanDefinitionRegistryPostProcessor源码分析

        我们知道,只要在一个Java类上加上@Component、@Service、@Controller等注解,就可以被加载到Spring容器中,除了以上方式,加了@Bean和@Import好像也可以将对象添加到Spring容器中,究竟Spring是如何实现这些功能的呢?让我们一起来一探究竟。

一、BeanFactoryPostProcessor后置处理器

        Spring IOC在实例化Bean对象之前,需要先读取Bean的相关属性,保存到BeanDefinition对象中,然后通过BeanDefinition对象,实例化Bean对象。

        如果想修改BeanDefinition对象中的属性,该怎么办呢?

        我们可以通过实现BeanFactoryPostProcessor接口实现。

//可以修改bean信息,但必须在bean实例化之前修改
@FunctionalInterface
public interface BeanFactoryPostProcessor {/*** Spring自动加载的某个BeanFactoryPostProcessor用于执行cglib动态代理*/void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}

(1)BeanFactoryPostProcessor的执行时机

        所有的BeanDefinitionPostProcessor后置处理器都是在spring的核心方法refresh()的invokeBeanFactoryPostProcessors(beanFactory);方法中执行的,主要用于修改BeanDefinition的属性信息。

//spring最主要的方法,context(上下文刷新)@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");/*** context刷新前的准备工作:主要是一些初始状态的赋值,环境配置的获取等**/// Prepare this context for refreshing.prepareRefresh();/*** 获取一个新的BeanFactory:如果已经context中存在BeanFactory,关闭该BeanFactory(先销毁工厂中的bean),再* 重新创建一个BeanFactory(DefaultListableBeanFactory类型)**/// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();/*** beanFactory的准备工作,创将一个标准的工厂(设置一些初始状态和初始值)*/// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {/*** 添加BeanFactory的增强器,留给用户扩展*/// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");/*** 执行BeanFactory中注册的BeanFactoryPostProcessor的相关逻辑*/// Invoke factory processors registered as beans in the context.//完成所谓的扫描和parse(解析,将类变成beanDefinition)// springboot的自动装配是在该方法执行的invokeBeanFactoryPostProcessors(beanFactory);/*** 注册bean的增强器(BeanPostProcessor)*/// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);beanPostProcess.end();/*** 国际化处理*/// Initialize message source for this context.initMessageSource();/*** 初始化应用事件广播器*/// Initialize event multicaster for this context.initApplicationEventMulticaster();/***在特定的上下文子类中初始化其他特殊bean,留给用户实现*/// Initialize other special beans in specific context subclasses.onRefresh();/*** 往广播器中注册监听器*/// Check for listener beans and register them.registerListeners();/*** 完成单例bean的初始化,同时也会执行registerBeanPostProcessors()时注册的beanPostProcessor*/// Instantiate all remaining (non-lazy-init) singletons.//开始实例化单例的类(需要validate和life)finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.// springboot启动TomcatfinishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.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();contextRefresh.end();}}}

(2)代码实现

public class SupplierObj{private String version;private int num;public SupplierObj() {}public String getVersion() {return version;}public void setVersion(String version) {this.version = version;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}@Overridepublic String toString() {return "SupplierObj{" +"version='" + version + '\'' +", num=" + num +'}';}
}

           这里设置属性version的值为”1.0.0“。

<!--只是设置属性值,并没有进行实例化,但是会把属性信息保存在bd中--><bean id="supplierObj" class="cn.crazy.newInstance.SupplierObj" ><property name="num" value="12"></property><property name="version" value="1.0.0"></property></bean>

        在这个接口里我们可以修改BeanDefinition的所有属性值,从而间接达到修改bean的信息的效果。

public class MyPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {GenericBeanDefinition beanDefinition = (GenericBeanDefinition)beanFactory.getBeanDefinition("supplierObj");//beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue();// 通过Supplier实现对象的实例化beanDefinition.setInstanceSupplier(() -> {SupplierObj supplierObj1 = new SupplierObj();return supplierObj1;});beanDefinition.getPropertyValues().addPropertyValue("version","通过BeanFactoryPostProcessor修订的版本0.0.2");}
}

控制台输出:

supplierObj = SupplierObj{version='通过BeanFactoryPostProcessor修订的版本0.0.2',  num=12}

(二)核心接口BeanDefinitionRegistryPostProcessor

        见名知义,这个后置处理器可以手动控制BeanDefinition的创建和注册。BeanDefinitionRegistryPostProcessor接口继承了BeanFactoryPostProcessor接口。

// BeanDefinitionRegistryPostProcessor可以注册更多的beanDefinition
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {/*** 在其标准初始化之后修改应用程序上下文的内部beanDefinition定义注册表*/void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;}

        查看Spring源码中关于BeanDefinitionRegistryPostProcessor 的实现类,其中ConfigurationClassPostProcessor是很重要的实现类。

        我们直接通过refresh()的invokeBeanFactoryPostProcessors(beanFactory)方法进入,查看所有BeanFactoryPostProcessor的执行。

// 实例化并调用所有已注册的BeanFactoryPostProcessorBean;
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {//getBeanFactoryPostProcessors()默认为空,可以通过context.addBeanFactoryPostProcessor();设置值// 代码块一:PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (!IN_NATIVE_IMAGE && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}

(1)代码块一:invokeBeanFactoryPostProcessors(),执行所有的BeanFactoryPostProcessors接口。

        其中这个方法有一个参数是通过getBeanFactoryPostProcessors()传入的,其默认为空,可以通过context.addBeanFactoryPostProcessor();设置值。

        这个方法也有很多中间变量,我们先把这些变量的作用简单说明下。

  • Set<String> processedBeans :存放所有满足条件的BeanDefinitionRegistryPostProcessor实现类的名称。
  • List<BeanFactoryPostProcessor> regularPostProcessors :存放标准的BeanFactoryPostProcessor实现类的集合(只实现了BeanFactoryPostProcessor接口的实现类)。
  • List<BeanDefinitionRegistryPostProcessor> registryProcessors:存放BeanDefinitionRegistryPostProcessor实现类的集合。
  • List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors:存放当前策略下执行的BeanDefinitionRegistryPostProcessor的集合。
  • String[] postProcessorNames:Spring容器中所有BeanDefinitionRegistryPostProcessor类型的postProcessor对应的名字(beanName)。
  • boolean reiterate:重复标识,初始值为true,因为BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法可能注册了BeanDefinitionRegistryPostProcessor类型的bd,直到调用完所有BeanDefinitionRegistryPostProcessors,不会出现新的BeanDefinitionRegistryPostProcessors时,设置为false。
  • List<BeanFactoryPostProcessor> priorityOrderedPostProcessors:存放实现了PriorityOrdered接口的BeanFactoryPostProcessor。
  • List<String> orderedPostProcessorNames :存放实现了Ordered接口的BeanFactoryPostProcessor。
  • List<String> nonOrderedPostProcessorNames:存放即没有实现PriorityOrdered接口也没有实现Ordered接口的BeanFactoryPostProcessor。

        这个方法大致总结为:

        1)如果方法参数中beanFactoryPostProcessors不为null,遍历beanFactoryPostProcessors。

        a. 如果其中的processor是BeanDefinitionRegistryPostProcessor类型。

        向上转型为BeanDefinitionRegistryPostProcessor类型,并执行其接口方法postProcessBeanDefinitionRegistry,同时将该processor加入registryProcessors集合。

        b. 如果其中的processor不是BeanDefinitionRegistryPostProcessor类型。

        将该processor加入regularPostProcessors集合。

        beanFactoryPostProcessors默认为空,可以通过context.addBeanFactoryPostProcessor();设置值。

        2)找到Spring容器中所有BeanDefinitionRegistryPostProcessor类型的postProcessor对应的名字,保存到字符串数组postProcessorNames中,遍历这个数组(这时只会找到Spring自己添加的)

        3)如果其中的processor是PriorityOrdered接口的实现类,从容器中getBean(postProcessorName)获取对应的BeanDefinitionRegistryPostProcessor,并将其放入currentRegistryProcessors * 同时将postProcessorName放入processedBeans集合。(这里不用担心会重复执行beanFactoryPostProcessors的processor,它是直接传入的值,并没有注册到容器中)遍历完成后,对currentRegistryProcessors进行排序,将currentRegistryProcessors中的元素全部加入registryProcessors集合中。遍历执行currentRegistryProcessors元素的postProcessBeanDefinitionRegistry(), *然后清空currentRegistryProcessors集合。

        4)重复步骤2,这是因为步骤3中的processor执行postProcessBeanDefinitionRegistry()方法时可能往容器中注册了BeanDefinitionRegistryPostProcessor类型的beanDefinition。

        5)如果其中的processor对应的name在processedBeans中不存在,且是Ordered接口的实现类,后续逻辑与步骤3一致。

        6)维护一个reiterate重复标识,初始值为true,进入while(reiterate),循环内容为执行步骤7

        7)将reiterate设置为false,重复步骤2,如果其中的processor对应的name在processedBeans中不存在,设置reiterate为true,后续逻辑与步骤3一致,进入下一轮循环,直到所有的beanName都在processedBeans中(没有找到新的BeanDefinitionRegistryPostProcessor类型的beanDefinition),结束while循环。

        8)遍历registryProcessors集合,执行BeanDefinitionRegistryPostProcessor类型的postProcessor的postProcessBeanFactory()方法。

         9)遍历regularPostProcessors集合,执行不是BeanDefinitionRegistryPostProcessor类型的postProcessor的postProcessBeanFactory()方法。

        10)找到Spring容器中所有BeanFactoryPostProcessor类型的postProcessor对应的名字,保存到字符串数组postProcessorNames中,遍历这个数组。(这里也是我们扩展的BeanFactoryPostProcessor的执行时机)

……

 BeanFactoryPostProcessor的处理逻辑与上述处理BeanDefinitionRegistryPostProcessor时类似,就不过多描述了。 也是先找PriorityOrdered接口的实现类,再找Ordered接口的实现类,最后找不是前面两种的普通实现类,放入对应的集合,排序,遍历执行接口方法

……

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {// Invoke BeanDefinitionRegistryPostProcessors first, if any.Set<String> processedBeans = new HashSet<>();if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;//存放标准的BeanFactoryPostProcessor的集合(只实现了BeanFactoryPostProcessor接口的实现类)List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();//存放BeanDefinitionRegistryPostProcessor的集合List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();//beanFactoryPostProcessors默认为空,可自己扩展for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {//先执行实现了BeanDefinitionRegistryPostProcessor接口的实现类中的postProcessBeanDefinitionRegistry()方法if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {//向上转型BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);}else {//不是BeanDefinitionRegistryPostProcessor类型的postProcessorregularPostProcessors.add(postProcessor);}}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!// Separate between BeanDefinitionRegistryPostProcessors that implement// PriorityOrdered, Ordered, and the rest.// 存放当前执行的BeanDefinitionRegistryPostProcessorList<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.//找到spring容器中所有BeanDefinitionRegistryPostProcessor类型的postProcessor对应的名字// 代码块二:默认的BeanDefinitionRegistryPostProcessors的注入时机//为什么只有一个?怎么来的?Spring在容器初始化时会自动注入一些必要的beanString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {//找实现了PriorityOrdered接口的实现类if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {//当前需要执行BeanDefinitionRegistryPostProcessor,执行完就会被清空//为什么能beanFactory.getBean()?虽然spring还没有实例化系统中bean,但是spring会提前实例化必须的bean()//为什么不直接new,而是选择getBean?有时可能程序员不使用系统默认的实现,可以自己指定实现/*** * @see AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(BeanDefinitionRegistry, Environment)*/currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));//将找到的Processor对应的名字放入processedBeans,方便后续根据名字判断processedBeans.add(ppName);}}// 代码块三:对后置处理器进行排序sortPostProcessors(currentRegistryProcessors, beanFactory);//将满足条件的Processors对象放入registryProcessorsregistryProcessors.addAll(currentRegistryProcessors);// Spring默认的后置处理器在这个方法里完成扫描// 代码块四:执行实现了PriorityOrdered接口的后置处理器的接口方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {//找实现了Ordered接口的实现类if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);// 执行实现了invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.boolean reiterate = true;while (reiterate) {reiterate = false;postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {//找非PriorityOrdered及非Ordered实现类对应BeanDefinitionRegistryPostProcessorif (!processedBeans.contains(ppName)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);//为什么设置为true//因为BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法可能注册了BeanDefinitionRegistryPostProcessor类型的bdreiterate = true;}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());currentRegistryProcessors.clear();}// Now, invoke the postProcessBeanFactory callback of all processors handled so far.//执行BeanDefinitionRegistryPostProcessor类型的postProcessor的postProcessBeanFactory()方法invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);//执行不是BeanDefinitionRegistryPostProcessor类型的postProcessor的postProcessBeanFactory()方法invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// Invoke factory processors registered with the context instance.invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, 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,加了注解(@Component)的后置处理器String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,// Ordered, and the rest.List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {if (processedBeans.contains(ppName)) {// skip - already processed in first phase above}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.sortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// Next, invoke the BeanFactoryPostProcessors that implement Ordered.List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());for (String postProcessorName : orderedPostProcessorNames) {orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// Finally, invoke all other BeanFactoryPostProcessors.List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());for (String postProcessorName : nonOrderedPostProcessorNames) {nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// Clear cached merged bean definitions since the post-processors might have// modified the original metadata, e.g. replacing placeholders in values...beanFactory.clearMetadataCache();}

(2)代码块二:默认的BeanDefinitionRegistryPostProcessors的注入时机。

        Spring默认注入的BeanDefinitionRegistryPostProcessors实现类是ConfigurationClassPostProcessor。在创建Spring容器中有一行代码new AnnotatedBeanDefinitionReader(this);Spring会在容器创建的时候自动注入一些必要的组件。

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {//调用构造函数,完成一些必须bd的注入this();//注册配置类,因为配置需要解析,一般不需要自己扫描//aliasMap.put//注册一些spring自身的bean,因为有些bean是无法通过扫描得到的//registerBeanDefinition(String beanName, BeanDefinition beanDefinition) --- this.beanDefinitionMap.put(beanName, beanDefinition);register(componentClasses);refresh();}public AnnotationConfigApplicationContext() {StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");// spring会自动注入一些必须的组件this.reader = new AnnotatedBeanDefinitionReader(this);createAnnotatedBeanDefReader.end();//spring提供api用来动态扫描注解//一般供扩展spring的时候用的this.scanner = new ClassPathBeanDefinitionScanner(this);}

        省略中间的一些代码,最终我们可以找到下面这个方法,registerAnnotationConfigProcessors(),在这个方法中往Spring容器中注入了一些BD。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);//初始化一些必要的bdif (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {// 注入ConfigurationClassPostProcessor.class的地方RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}

 (3)代码块三:sortPostProcessors(),对后置处理器进行排序

        通过排序比较器进行排序。

private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {// Nothing to sort?if (postProcessors.size() <= 1) {return;}Comparator<Object> comparatorToUse = null;if (beanFactory instanceof DefaultListableBeanFactory) {comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();}if (comparatorToUse == null) {comparatorToUse = OrderComparator.INSTANCE;}postProcessors.sort(comparatorToUse);}

(4)代码块四:invokeBeanDefinitionRegistryPostProcessors(),执行实现了PriorityOrdered接口的后置处理器的接口方法 。

        Spring核心类ConfigurationClassPostProcessor在这个方法里主要完成项目的扫描解析的功能。

@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {// 计算registry的hashCodeint registryId = System.identityHashCode(registry);if (this.registriesPostProcessed.contains(registryId)) {throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);}if (this.factoriesPostProcessed.contains(registryId)) {throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);}this.registriesPostProcessed.add(registryId);//代码五:完成扫描的逻辑processConfigBeanDefinitions(registry);}

(5)代码块五:processConfigBeanDefinitions(),构建和验证配置类,完成配置类的扫描。

        这个方法大致总结为:

        1)创建一个configCandidates集合变量,存放候选配置类。获取容器中所有的beanDefinition对应的beanName作为候选对象(candidateNames)。(取调用register()加入的bd和spring内置的bd(spring提前初始化的bd))。

        2)遍历candidateNames,获取对应的beanDefinition,判断这个beanDefinition是否被解析过(解析过的配置类ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE有值),判断这个beanDefinition是否候选配置类对象,如果是,添加到configCandidates候选配置类集合中。

        3)对configCandidates候选配置类集合进行排序,并将其封装到candidates集合中。创建配置类解析器对candidates集合中的候选对象进行解析,并对解析出来的结果进行验证。

        4)注册所有通过配置类找到的需要注册到容器中的元素(需转换为BD对象后再进行注册)。清空candidates集合。

        5)因为会新注册一些bd到容器中,需要对新注册进来的那部分bd继续进行解析。(将新注册的符合条件的bd加入candidates集合,如果candidates为空,说明完成所有候选配置类的解析。)

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {// 将配置类放入这个候选配置类集合List<BeanDefinitionHolder> configCandidates = new ArrayList<>();//获取调用register()加入bd和spring内置的bd(spring提前初始化的bd)String[] candidateNames = registry.getBeanDefinitionNames();for (String beanName : candidateNames) {BeanDefinition beanDef = registry.getBeanDefinition(beanName);//这个类是否被解析过(解析过的配置类ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE有值)if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {if (logger.isDebugEnabled()) {logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);}}//代码六 :判断beanDef是否为配置类else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {// 构建BeanDefinitionHolder对象后加入configCandidates集合configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));}}// Return immediately if no @Configuration classes were foundif (configCandidates.isEmpty()) {return;}// 对集合元素进行排序// Sort by previously determined @Order value, if applicableconfigCandidates.sort((bd1, bd2) -> {int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());return Integerpare(i1, i2);});// Detect any custom bean name generation strategy supplied through the enclosing application contextSingletonBeanRegistry sbr = null;if (registry instanceof SingletonBeanRegistry) {sbr = (SingletonBeanRegistry) registry;if (!this.localBeanNameGeneratorSet) {BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);if (generator != null) {thisponentScanBeanNameGenerator = generator;this.importBeanNameGenerator = generator;}}}if (this.environment == null) {this.environment = new StandardEnvironment();}// Parse each @Configuration class// 解析每个加了@Configuration的类ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, thisponentScanBeanNameGenerator, registry);//将配置类封装到candidates集合Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);// 已经完成解析的ConfigurationClassSet<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());do {StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");//代码八:完成配置类的解析parser.parse(candidates);// 验证在@Configuration属性proxyBeanMethods=true时,其@Bean标记的方法是否符合要求parser.validate();Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());configClasses.removeAll(alreadyParsed);// Read the model and create bean definitions based on its contentif (this.reader == null) {this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}//其中一个重要的代码是:循环map,执行map中ImportBeanDefinitionRegistrar的registerBeanDefinitions()方法// 代码二十:注册所有通过配置类找到的需要注册到容器中的元素(需转换为BD对象后再进行注册)this.reader.loadBeanDefinitions(configClasses);alreadyParsed.addAll(configClasses);processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();candidates.clear();// 因为会新注册一些bd到容器中,需要对新注册进来的那部分bd进行解析if (registry.getBeanDefinitionCount() > candidateNames.length) {String[] newCandidateNames = registry.getBeanDefinitionNames();Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));Set<String> alreadyParsedClasses = new HashSet<>();for (ConfigurationClass configurationClass : alreadyParsed) {alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());}for (String candidateName : newCandidateNames) {if (!oldCandidateNames.contains(candidateName)) {BeanDefinition bd = registry.getBeanDefinition(candidateName);if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&!alreadyParsedClasses.contains(bd.getBeanClassName())) {candidates.add(new BeanDefinitionHolder(bd, candidateName));}}}candidateNames = newCandidateNames;}}while (!candidates.isEmpty());// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classesif (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());}if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {// Clear cache in externally provided MetadataReaderFactory; this is a no-op// for a shared cache since it'll be cleared by the ApplicationContext.((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();}}


(6)代码块六 :checkConfigurationClassCandidate(),检查给定的beanDefinition是否是配置类的候选对象。

        这个方法大致总结如下:

        1)获取beanDefinition的className,判断beanDefinition是否为是AnnotatedBeanDefinition类型且className与元数据中的className一致。

        2)如果是,将beanDefinition转换成AnnotatedBeanDefinition类型,并获取其中的元数据信息。

        3)从元数据中获取@Configuration注解的参数信息,如果为beanDefinition没有加@Configuration注解,返回false。

        4)如果@Configuration的属性proxyBeanMethods的值为true,该配置类为全配置类,并设置

BD的属性CONFIGURATION_CLASS_ATTRIBUTE的值为CONFIGURATION_CLASS_FULL。

        5)如果@Configuration的属性proxyBeanMethods的值为false,且代码七(步骤7)返回true,

该配置类为简洁配置类,并设置

BD的属性CONFIGURATION_CLASS_ATTRIBUTE的值为CONFIGURATION_CLASS_LITE。

        6)BD的属性CONFIGURATION_CLASS_ATTRIBUTE设置完成后,返回true。(BD的属性CONFIGURATION_CLASS_ATTRIBUTE的值如果buwei空,说明该配置类已经被解析过了)

// 检查给定的BeanDefinition是否是配置类的候选对象// 如果是配置类,设置其配置类的类型(全配置类还是简洁配置类?)public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {String className = beanDef.getBeanClassName();if (className == null || beanDef.getFactoryMethodName() != null) {return false;}//保存类的元数据AnnotationMetadata metadata;//是AnnotatedBeanDefinition类型的独立的类if (beanDef instanceof AnnotatedBeanDefinition &&className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {// Can reuse the pre-parsed metadata from the given BeanDefinition...metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();}else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {// Check already loaded Class if present...// since we possibly can't even load the class file for this Class.Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();// 这几个接口的实现类Spring不认为是候选配置类if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||BeanPostProcessor.class.isAssignableFrom(beanClass) ||AopInfrastructureBean.class.isAssignableFrom(beanClass) ||EventListenerFactory.class.isAssignableFrom(beanClass)) {return false;}metadata = AnnotationMetadata.introspect(beanClass);}else {try {MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);metadata = metadataReader.getAnnotationMetadata();}catch (IOException ex) {if (logger.isDebugEnabled()) {logger.debug("Could not find class file for introspecting configuration annotations: " +className, ex);}return false;}}//获取类上Configuration注解的参数信息Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());//boolean proxyBeanMethods() default true;//CONFIGURATION_CLASS_FULL和CONFIGURATION_CLASS_LITE值的意义?Spring中Aop会用到这个标识if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {// 全配置类或者是完整的配置类beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);}//Configuration的proxyBeanMethods() = false  || [Component、ComponentScan、ImportResource、ImportResource、@Bean方法中一个]则为lite// 代码块七:检查给定的元数据是否为配置类候选项else if (config != null || isConfigurationCandidate(metadata)) {// 简洁的配置类beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);}else {return false;}// It's a full or lite configuration candidate... Let's determine the order value, if any.Integer order = getOrder(metadata);if (order != null) {beanDef.setAttribute(ORDER_ATTRIBUTE, order);}return true;}

 (7)代码块七:isConfigurationCandidate(metadata),检查给定的metadata元数据是否为配置类候选项。

         当前的元数据是否包含@Component、@ComponentScan、@ImportResource、@Bean方法中一个。是则返回true,否则返回false。

// 检查给定的元数据是否为配置类候选项public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {// Do not consider an interface or an annotation...if (metadata.isInterface()) {return false;}/*** static {* 		candidateIndicators.add(Component.class.getName());* 		candidateIndicators.add(ComponentScan.class.getName());* 		candidateIndicators.add(Import.class.getName());* 		candidateIndicators.add(ImportResource.class.getName());*        }*/// Any of the typical annotations found?for (String indicator : candidateIndicators) {if (metadata.isAnnotated(indicator)) {return true;}}// Finally, let's look for @Bean methods...try {//类里面有包含@Bean的方法return metadata.hasAnnotatedMethods(Bean.class.getName());}catch (Throwable ex) {if (logger.isDebugEnabled()) {logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);}return false;}}

(8)代码块八:parse()-->processConfigurationClass(),解析配置类。

        这个方法大致总结为:

        1)判断是否满足一些条件配置需要跳过的情况,如果是,直接return。

        2)处理多层嵌套Import导入问题及(不同配置类)多次Import(同一配置类)问题。

        3)递归地处理配置类及其超类的层次结构,封装成SourceClass。

        4)解析@Configuration配置类,解析完成后将其放入this.configurationClasses中,这就是为什么通过别的配置类@Import的配置类在这个方法获取缓存时(this.configurationClasses.get())会有值。
            

    // 解析配置类public void parse(Set<BeanDefinitionHolder> configCandidates) {for (BeanDefinitionHolder holder : configCandidates) {BeanDefinition bd = holder.getBeanDefinition();try {if (bd instanceof AnnotatedBeanDefinition) {// 解析AnnotatedBeanDefinition类型的bdparse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());}
//省略其他类型bd的解析逻辑,我们选择比较经典的AnnotatedBeanDefinition类型的bd进行源码解析
……}this.deferredImportSelectorHandler.process();}
// 解析AnnotatedBeanDefinition类型的bd
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);}// 处理配置类protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {// 跳过某些条件配置生效的情况if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {return;}// 从缓存中获取ConfigurationClass existingClass = this.configurationClasses.get(configClass);if (existingClass != null) {// 这个配置类是否通过其配置类加@Importe注解引入的if (configClass.isImported()) {// 多个配置类通过@Importe注解引入的同一个配置类时,为trueif (existingClass.isImported()) {existingClass.mergeImportedBy(configClass);}// Otherwise ignore new imported config class; existing non-imported class overrides it.return;}else {// Explicit bean definition found, probably replacing an import.// Let's remove the old one and go with the new one.// 嵌套@Importe会进入这个方法this.configurationClasses.remove(configClass);this.knownSuperclasses.values().removeIf(configClass::equals);}}// Recursively process the configuration class and its superclass hierarchy.SourceClass sourceClass = asSourceClass(configClass, filter);do {//doXXX一般都是真正处理逻辑的方法// 代码十:完成配置类的解析sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);}while (sourceClass != null);this.configurationClasses.put(configClass, configClass);}

(9)代码块九:asSourceClass()递归地处理配置类及其超类层次结构,封装成SourceClass。

        Spring中的所有一切皆Source,class也是一种Source。

private SourceClass asSourceClass(ConfigurationClass configurationClass, Predicate<String> filter) throws IOException {AnnotationMetadata metadata = configurationClass.getMetadata();if (metadata instanceof StandardAnnotationMetadata) {return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass(), filter);}return asSourceClass(metadata.getClassName(), filter);}public SourceClass(Object source) {this.source = source;if (source instanceof Class) {this.metadata = AnnotationMetadata.introspect((Class<?>) source);}else {this.metadata = ((MetadataReader) source).getAnnotationMetadata();}}

 (10)代码块十: doProcessConfigurationClass(),处理配置类的解析。

        这个方法大致总结为:

        1)如果配置类有@Component注解,递归处理其成员也是配置类的情况。

        2)如果配置类有@PropertySource注解,解析相关属性信息,完成配置文件的加载。

        3)如果配置类有@ComponentScans或@ComponentScan注解,借助注解扫描器扫描指定目录下的class文件,找到符合条件的beanDefinition添加到候选集合,并完成注册,返回候选集合。

        4)遍历候选集合中的beanDefinition,如果beanDefinition是配置类,执行解析配置类的代码逻辑。

        5)如果配置类有@Import注解,递归查找@Import中的值,根据class类型不同,进行不同的处理。

        6) 如果配置类有@ImportResource 注解,解析相关属性信息,完成配置文件的加载。

        7)递归获取加了@Bean的方法,并加入this.beanMethods。方便后续将这些method封装成beanDefinition对象。

        8)处理接口,遍历当前configClass实现的所有接口,如果接口中有@Bean标记的方法,将这个方法加入this.beanMethods。

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)throws IOException {// Component配置类的解析if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes first// 递归处理成员也是配置类的情况// 递归地处理任何成员(嵌套)类[内部类有加Component、ComponentScan、Import、ImportSource等注解的情况]processMemberClasses(configClass, sourceClass, filter);}// Process any @PropertySource annotationsfor (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {if (this.environment instanceof ConfigurableEnvironment) {// 代码十一:处理PropertySources加载配置文件processPropertySource(propertySource);}else {logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +"]. Reason: Environment must implement ConfigurableEnvironment");}}// 处理@ComponentScan扫描项目路径// Process any @ComponentScan annotationsSet<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);if (!componentScans.isEmpty() &&!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for (AnnotationAttributes componentScan : componentScans) {// 代码十二:解析ComponentScan注解//扫描解析的逻辑// The config class is annotated with @ComponentScan -> perform the scan immediatelySet<BeanDefinitionHolder> scannedBeanDefinitions =thisponentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());// Check the set of scanned definitions for any further config classes and parse recursively if neededfor (BeanDefinitionHolder holder : scannedBeanDefinitions) {BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();if (bdCand == null) {bdCand = holder.getBeanDefinition();}// 是否为配置类if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {// 解析配置类parse(bdCand.getBeanClassName(), holder.getBeanName());}}}}//代码块十六:处理@Import注解引入的class(mybatis的扩展点)// Process any @Import annotationsprocessImports(configClass, sourceClass, getImports(sourceClass), filter, true);// Process any @ImportResource annotations// 处理@ImportResource加载配置文件AnnotationAttributes importResource =AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);if (importResource != null) {String[] resources = importResource.getStringArray("locations");Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");for (String resource : resources) {String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);configClass.addImportedResource(resolvedResource, readerClass);}}// Process individual @Bean methods// 获取加了@Bean的方法,并加入this.beanMethodsSet<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// 处理接口,遍历当前configClass实现的所有接口,如果接口中有@Bean标记的方法,将这个方法加入this.beanMethods// Process default methods on interfacesprocessInterfaces(configClass, sourceClass);// Process superclass, if anyif (sourceClass.getMetadata().hasSuperClass()) {String superclass = sourceClass.getMetadata().getSuperClassName();if (superclass != null && !superclass.startsWith("java") &&!this.knownSuperclasses.containsKey(superclass)) {this.knownSuperclasses.put(superclass, configClass);// Superclass found, return its annotation metadata and recursereturn sourceClass.getSuperClass();}}// No superclass -> processing is completereturn null;}

(11)代码块十一:processPropertySource(),处理PropertySources加载配置文件。

        @PropertySource注解用于指定资源文件读取的位置,它不仅能读取properties文件,也能读取xml文件,并且通过YAML解析器,配合自定义PropertySourceFactory实现解析YAML文件。

private void processPropertySource(AnnotationAttributes propertySource) throws IOException {// 处理name属性String name = propertySource.getString("name");if (!StringUtils.hasLength(name)) {name = null;}// 处理encoding属性String encoding = propertySource.getString("encoding");if (!StringUtils.hasLength(encoding)) {encoding = null;}String[] locations = propertySource.getStringArray("value");Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");// 忽略找不到的情况,找不到资源文件不会报错boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));for (String location : locations) {try {// 加载资源文件String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);Resource resource = this.resourceLoader.getResource(resolvedLocation);addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));}catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {// Placeholders not resolvable or resource not found when trying to open itif (ignoreResourceNotFound) {if (logger.isInfoEnabled()) {logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());}}else {throw ex;}}}}

 (12)代码块十二:parse(),处理@componentScan注解。

        这个方法大致总结为:

        1)创建一个注解扫描器,可以通过@ComponentScan(useDefaultFilters = boolean)决定是否使用spring默认的扫描器TypeFilter。读取注解中的属性信息,完成注解扫描器对应的属性值设置。

        2)通过扫描器扫描basePackages下的class,然后解析成对应的bd。

// 解析@ComponentScan注解public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {//可以通过@ComponentScan(useDefaultFilters = boolean)决定是否使用spring默认的扫描器// 创建一个注解扫描器ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);//读取注解中的属性,完成注解扫描器对应的属性值设置Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :BeanUtils.instantiateClass(generatorClass));ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");if (scopedProxyMode != ScopedProxyMode.DEFAULT) {scanner.setScopedProxyMode(scopedProxyMode);}else {Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));}scanner.setResourcePattern(componentScan.getString("resourcePattern"));for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {for (TypeFilter typeFilter : typeFiltersFor(filter)) {scanner.addIncludeFilter(typeFilter);}}for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {for (TypeFilter typeFilter : typeFiltersFor(filter)) {scanner.addExcludeFilter(typeFilter);}}boolean lazyInit = componentScan.getBoolean("lazyInit");if (lazyInit) {scanner.getBeanDefinitionDefaults().setLazyInit(true);}Set<String> basePackages = new LinkedHashSet<>();// 扫描的项目路径String[] basePackagesArray = componentScan.getStringArray("basePackages");for (String pkg : basePackagesArray) {String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);Collections.addAll(basePackages, tokenized);}for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {basePackages.add(ClassUtils.getPackageName(clazz));}if (basePackages.isEmpty()) {basePackages.add(ClassUtils.getPackageName(declaringClass));}scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {@Overrideprotected boolean matchClassName(String className) {return declaringClass.equals(className);}});//代码十三:调用doScan()扫描basePackages下的类,然后解析成对应的bdreturn scanner.doScan(StringUtils.toStringArray(basePackages));}

        创建扫描器时默认使用Spring注册的TypeFilters。

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");this.registry = registry;//关键代码,Spring内部默认为true,使用默认的Filtersif (useDefaultFilters) {registerDefaultFilters();}setEnvironment(environment);setResourceLoader(resourceLoader);}protected void registerDefaultFilters() {//这里传了一个Component.class//后续spring扫描一个resource出来之后需要判断他是否合理,核心代码this.includeFilters.add(new AnnotationTypeFilter(Component.class));ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.}try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}

(13)代码块十三:doScan(),扫描basePackages下的class,然后解析成对应的bd。

        1)创建一个Set集合变量beanDefinitions,用来存放解析后的beanDefinition。

        2)遍历扫描路径,返回该目录下满足条件的候选集合。

        3)遍历候选集合,获取当前beanDefinition的beanName,并根据beanDefinition的类型设置不同的默认属性。

        4)检查是否需要注册当前beanDefinition,如果容器中不存在beanName对应的组件,则需要注册。根据当前beanDefinition和对应的beanName构建BeanDefinitionHolder对象,将holder对象添加到beanDefinitions集合,并将其注册到容器中(beanDefinitionMap.put(beanName, beanDefinition);)。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();for (String basePackage : basePackages) {//代码块十四:找到满足条件的候选组件Set<BeanDefinition> candidates = findCandidateComponents(basePackage);for (BeanDefinition candidate : candidates) {ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) {// 设置一些默认属性postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}if (candidate instanceof AnnotatedBeanDefinition) {// 将注解信息设置为相应的bd属性AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}// 检查是否需要注册candidate,容器中不存在beanName对应的组件if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}

(14)代码块十四:findCandidateComponents(),找到满足条件的候选组件

        这个方法大致总结为:

        1)获取扫描目录路径,并将该目录下的所有文件封装为Spring中的Source(Source是对URL的扩展,提供了更多获取文件信息的方法)。

        2)遍历所有的source,判断source资源是否可读,如果可读,获取source的元数据信息。

        3)判断元数据中的注解是否满足要求,this.includeFilters中的TypeFilter与metadataReader是否匹配。默认扫描的注解为@Component。

        4)如果匹配,结合元数据和source封装为ScannedGenericBeanDefinition对象,接着判断给定这个BD对象的类型是否符合要求。如果符合要求,将这个BD加入候选集合中,返回这个集合。

public Set<BeanDefinition> findCandidateComponents(String basePackage) {//如果有添加spring索引辅助jar包,执行这块代码if (thisponentsIndex != null && indexSupportsIncludeFilters()) {return addCandidateComponentsFromIndex(thisponentsIndex, basePackage);}else {//默认执行这块代码return scanCandidateComponents(basePackage);}}//扫描出符合规则的候选组件private Set<BeanDefinition> scanCandidateComponents(String basePackage) {Set<BeanDefinition> candidates = new LinkedHashSet<>();try {String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;//Resource扩展了URL,提供了更丰富的功能Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);boolean traceEnabled = logger.isTraceEnabled();boolean debugEnabled = logger.isDebugEnabled();// 遍历指定目录下的classfor (Resource resource : resources) {if (traceEnabled) {logger.trace("Scanning " + resource);}if (resource.isReadable()) {try {//类的元数据MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);//代码十五:判断注解是否满足要求if (isCandidateComponent(metadataReader)) {ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);sbd.setSource(resource);//Mybatis的扩展点:Mybatis为什么可以扫描接口//代码十六 :判断给定bd的类型是否符合要求if (isCandidateComponent(sbd)) {if (debugEnabled) {logger.debug("Identified candidate component class: " + resource);}candidates.add(sbd);}……}}catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return candidates;}protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}//如果想解析其他注解(Mybatis的Mapper注解),可以往includeFilters中添加对应的注解//this.includeFilters是否有与metadataReader匹配的TypeFilter//如果想要在spring中添加自定义扫描器,可以考虑将自定义的扫描加入this.includeFilters集合for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}return false;}protected void registerDefaultFilters() {//这里传了一个Component.class//后续spring扫描一个resource出来之后需要判断他是否合理,核心代码this.includeFilters.add(new AnnotationTypeFilter(Component.class));ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.}try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}

(15)代码块十五:isCandidateComponent(),判断给定的beanDefinition是否候选组件 。

       方法重载,这两个方法的功能如下:

    (i)this.includeFilters中的TypeFilter与metadataReader是否匹配。

        这里是扫描器的工作原理,自定义的扫描时可以将要扫描的注解类的TypeFilter加入this.includeFilters集合。

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}//如果想解析其他注解(Mybatis的Mapper注解),可以往includeFilters中添加对应的注解//this.includeFilters是否有与metadataReader匹配的TypeFilter//如果想要在spring中添加自定义扫描器,可以考虑将自定义的扫描加入this.includeFilters集合for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}return false;}

        (ii)判断给定的beanDefinition类类型是否满足候选条件

        Spring中的扫描是不能扫描接口的,除非这个接口加了@Lookup注解。我们知道在接口上加Mybatis注解是,能被扫描成Mapper,这首因为Mybatis修改了这个判断。

protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {AnnotationMetadata metadata = beanDefinition.getMetadata();//判断类类型是否满足候选条件(顶层类或加了@Lookup的抽象类等)return (metadata.isIndependent() && (metadata.isConcrete() ||(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));}default boolean isConcrete() {return !(isInterface() || isAbstract());}

        isIndependent()判断是一个class是独立的,有两种情况:一.它是top-level的(我们正常创建的类)。 二.它是nested class也就是静态内部类。

        class分为5中类型:

  • top level class

  • nested class (静态内部类)

  • inner class(非静态内部类)

  • local class(在方法内定义的类)

  • anonymous class(匿名类)

三、处理@Import注解 

        因为上一章节太长了,而且@Import注解比较重要,所有开了一个新的章节来说。使用@Import注解引入的class是很常有的一个功能,同时也是mybatis的扩展点。下面来看看Spring是如何处理@Import注解的。

//代码块十六:处理@Import注解引入的class(mybatis的扩展点)// Process any @Import annotationsprocessImports(configClass, sourceClass, getImports(sourceClass), filter, true);// 返回@Import引入的classprivate Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {Set<SourceClass> imports = new LinkedHashSet<>();Set<SourceClass> visited = new LinkedHashSet<>();collectImports(sourceClass, imports, visited);return imports;}//递归收集所有@Import的值private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)throws IOException {if (visited.add(sourceClass)) {// 获取class上所有的注解for (SourceClass annotation : sourceClass.getAnnotations()) {String annName = annotation.getMetadata().getClassName();if (!annName.equals(Import.class.getName())) {// 不是@Import的注解上可能又加了@Import注解,所以要递归查找collectImports(annotation, imports, visited);}}imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));}}

 (1)代码块十六: processImports(),处理@Import注解(mybatis的扩展点)。

        这个方法大致总结为:

        1)如果importCandidates为null,直接返回。(importCandidates为容器中所有通过@Import导入的class的集合)

        2)进行一些检查,如果检查不通过,报错。

        3)遍历importCandidates,

         a. 如果当前的candidates是ImportSelector类型,反射创建ImportSelector对象,执行该对象的selectImports()方法,将返回值封装成Source集合,递归处理@Import注解。

        b.如果当前的candidates是ImportBeanDefinitionRegistrar类型,通过反射创建ImportBeanDefinitionRegistrar对象,并加入configClass的importBeanDefinitionRegistrars集合中。

        c.如果当前的candidates不是ImportSelector类型,也不是ImportBeanDefinitionRegistrar类型,把它当成@Configuration配置类进行处理。

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,boolean checkForCircularImports) {// 如果没有@Import注解,直接返回if (importCandidates.isEmpty()) {return;}// checkForCircularImports = trueif (checkForCircularImports && isChainedImportOnStack(configClass)) {// 报错this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));}else {this.importStack.push(configClass);try {// 遍历@Import引入的类for (SourceClass candidate : importCandidates) {// 如果candidate是ImportSelector类型if (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector -> delegate to it to determine imports// 返回Class对象,如果是this.source是Class类型直接返回,或者通过this.source得到beanName,通过Class.forName(beanName)返回Class// 代码十七:获取candidate的Class对象Class<?> candidateClass = candidate.loadClass();// 反射创建ImportSelector对象ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,this.environment, this.resourceLoader, this.registry);//exclusionFilter,用于从导入候选对象中排除类Predicate<String> selectorFilter = selector.getExclusionFilter();if (selectorFilter != null) {exclusionFilter = exclusionFilter.or(selectorFilter);}// 如果selector是DeferredImportSelector类型,执行默认的ImportSelector的处理if (selector instanceof DeferredImportSelector) {this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);}else {// 获取selector.selectImports()的返回值String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());// 封装成SourceCollection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);// 递归处理@Import注解processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);}}//如果@Import引入了ImportBeanDefinitionRegistrar类型的class,通过反射创建出来,并加入configClass的importBeanDefinitionRegistrars集合中// @Import注解引入的class能被创建的原因else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {// Candidate class is an ImportBeanDefinitionRegistrar ->// delegate to it to register additional bean definitions// 获取candidate的Class对象Class<?> candidateClass = candidate.loadClass();//实例化对象// 代码块十八:通过反射实例化对象ImportBeanDefinitionRegistrar registrar =ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,this.environment, this.resourceLoader, this.registry);//将实例化后的对象放入importBeanDefinitionRegistrars集合中(没有立即执行ImportBeanDefinitionRegistrar,后面循环这个map进行执行)//public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {//		this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);//	}// 代码十九:将实例化后的对象放入importBeanDefinitionRegistrars集合中configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());}else {// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->// process it as an @Configuration classthis.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());// 如果@Import引入的class不是ImportSelector or ImportBeanDefinitionRegistrar,把它当成@Configuration配置类进行处理processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);}}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +configClass.getMetadata().getClassName() + "]", ex);}finally {this.importStack.pop();}}}

(2)代码块十七:loadClass(),获取candidate的Class对象。

        返回Class对象,如果是this.source是Class类型直接返回,或者通过this.source得到beanName,通过Class.forName(beanName)返回Class对象。

public Class<?> loadClass() throws ClassNotFoundException {if (this.source instanceof Class) {return (Class<?>) this.source;}String className = ((MetadataReader) this.source).getClassMetadata().getClassName();return ClassUtils.forName(className, resourceLoader.getClassLoader());}

(3)代码块十八:instantiateClass(),通过反射实例化对象。

static <T> T instantiateClass(Class<?> clazz, Class<T> assignableTo, Environment environment,ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {Assert.notNull(clazz, "Class must not be null");Assert.isAssignable(assignableTo, clazz);if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());//通过反射创建clazz对象T instance = (T) createInstance(clazz, environment, resourceLoader, registry, classLoader);//扩展点:执行这个实例的awareMethods,这个实例是否有实现xxAware接口ParserStrategyUtils.invokeAwareMethods(instance, environment, resourceLoader, registry, classLoader);return instance;}private static Object createInstance(Class<?> clazz, Environment environment,ResourceLoader resourceLoader, BeanDefinitionRegistry registry,@Nullable ClassLoader classLoader) {Constructor<?>[] constructors = clazz.getDeclaredConstructors();if (constructors.length == 1 && constructors[0].getParameterCount() > 0) {try {Constructor<?> constructor = constructors[0];Object[] args = resolveArgs(constructor.getParameterTypes(),environment, resourceLoader, registry, classLoader);// 如果只有一个构造器,且是有参构造器,使用这个构造器实例化对象return BeanUtils.instantiateClass(constructor, args);}catch (Exception ex) {throw new BeanInstantiationException(clazz, "No suitable constructor found", ex);}}// 通过无参构造器实例话对象return BeanUtils.instantiateClass(clazz);}

 (4)代码块十九:addImportBeanDefinitionRegistrar(),将实例化后的对象放入importBeanDefinitionRegistrars集合中。

        将实例化后的对象放入importBeanDefinitionRegistrars集合中(没有立即执行ImportBeanDefinitionRegistrar,后面循环这个map进行执行)

public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
}

(5)代码块二十:loadBeanDefinitions(),注册所有通过配置类找到的需要注册到容器中的元素。

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();for (ConfigurationClass configClass : configurationModel) {loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);}}

       这个方法是注册所有通过配置类找到的需要注册到容器中的元数据(或者称为元素合适一些?),将其封装为beanDefinition对象后注册到容器中 。

// 这个方法是注册所有通过配置类找到的需要注册到容器中的元数据(或者称为元素合适一些?),将其封装为bd后注册到容器中private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {if (trackedConditionEvaluator.shouldSkip(configClass)) {String beanName = configClass.getBeanName();if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {this.registry.removeBeanDefinition(beanName);}this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());return;}if (configClass.isImported()) {registerBeanDefinitionForImportedConfigurationClass(configClass);}for (BeanMethod beanMethod : configClass.getBeanMethods()) {// 获取@Bean标记方法对应的元数据,name等封装成相应beanDefinition,注册到容器中loadBeanDefinitionsForBeanMethod(beanMethod);}loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());// 通过ImportBeanDefinitionRegistrar实例化bd,遍历注册this.importBeanDefinitionRegistrars中的对象loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());}

         这里遍历步骤4(代码十九)中的Map,执行ImportBeanDefinitionRegistrar对象的registerBeanDefinitions()方法。

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {// 遍历this.importBeanDefinitionRegistrars中的对象,执行其registerBeanDefinitions()方法registrars.forEach((registrar, metadata) ->registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));}

        至此,执行完了 processConfigBeanDefinitions()方法的流程,完成了配置类的扫描解析。

四、Mybatis对ImportBeanDefinitionRegistrar的扩展

        我们看看Mybatis核心注解@MapperScan,可以看到其通过@Import()引入了MapperScannerRegistrar.class

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan {
……
}

(1)老版本Mybatis的MapperScannerRegistrar

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
……
//ImportBeanDefinitionRegistrar的接口方法//老版的mybatis在这个方法中创建了scanner完成扫描@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);……scanner.registerFilters();scanner.doScan(StringUtils.toStringArray(basePackages));}

(2)新版本Mybatis的MapperScannerRegister

        新版的Mybatis的实现。新版的mybatis在registerBeanDefinitions()方法中创建了BeanDefinitionRegistryPostProcessor类型的对象MapperScannerConfigurer.

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {AnnotationAttributes mapperScanAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));if (mapperScanAttrs != null) {registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry,generateBaseBeanName(importingClassMetadata, 0));}}void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs,BeanDefinitionRegistry registry, String beanName) {BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);……}

        在 MapperScannerConfigurer类实现的BeanDefinitionRegistryPostProcessor接口方法中创建扫描器,完成自定义注解的扫描解析。

public class MapperScannerConfigurerimplements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {……@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {if (this.processPropertyPlaceHolders) {processPropertyPlaceHolders();}ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);scanner.setAddToConfig(this.addToConfig);scanner.setAnnotationClass(this.annotationClass);scanner.setMarkerInterface(this.markerInterface);scanner.setSqlSessionFactory(this.sqlSessionFactory);scanner.setSqlSessionTemplate(this.sqlSessionTemplate);scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);scanner.setResourceLoader(this.applicationContext);scanner.setBeanNameGenerator(this.nameGenerator);scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);if (StringUtils.hasText(lazyInitialization)) {scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization));}scanner.registerFilters();scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));}……
}

(3)新版和老版的mybatis的区别

  • ​老版的mybatis扫描的入口是@MapperScan的ImportBeanDefinitionRegistrar,如果不加@MapperScan,mybatis无法完成扫描。新版的mybatis可以不加@MapperScan,而是通过向spring容器中注入MapperScannerConfigurer即可完成扫描。
  • 执行时机不同,老版扫描发生在ConfigurationClassPostProcessor进行扫描解析配置类时。新版的执行时机要晚一些,新版的扫描在执行普通的BeanDefinitionRegistryPostProcessor类(没有实现PriorityOrdered和Order接口)的接口方法时完成的。

五、总结

        通过上述的源码分析,我们可以发现不同类型的BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的执行时机(执行顺序)。同时对Spring核心类ConfigurationClassPostProcessor进行源码分析时,发现它的功能非常强大,其中包括:

        1.加载配置文件(解析@PropertySource和@ImportResource 注解的相关属性信息,完成配置文件的加载。)

        2.扫描解析@Component注解,将符合条件的组件创建为beanBefinition。(扩展点:自定义扫描器如何工作?Mybatis为什么能扫描接口类?后续详细展开)

        3.对@Import注解导入的核心接口ImportBeanDefinitionRegistrar的处理。(扩展点:Mybatis注解扫描的时机?)

        4.将@Bean标识得方法转换成对应的beanDefinition。

        5.生成CGLIB代理对象。(BeanFactoryPostProcessor接口方法实现的功能,后续详细展开)


      

更多推荐

Spring核心扩展点BeanDefinitionRegistryPostProcessor源码分析

本文发布于:2023-12-08 04:08:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1672308.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:源码   核心   Spring   BeanDefinitionRegistryPostProcessor

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!