当前位置 : 主页 > 编程语言 > java >

Spring5 IOC容器解析——注解配置的资源定位、加载、解析、注册分析

来源:互联网 收集:自由互联 发布时间:2023-02-04
AnnotationConfigApplicationContext 使用AnnotationConfigApplicationContext可以实现基于Java的配置类(包括各种注解)加载Spring的应用上下文。避免使用application.xml进行配置。相比XML配置,更加便捷。 一、

AnnotationConfigApplicationContext

使用AnnotationConfigApplicationContext可以实现基于Java的配置类(包括各种注解)加载Spring的应用上下文。避免使用application.xml进行配置。相比XML配置,更加便捷。

一、被@Configuration标记的Bean的资源定位、加载、解析、注册分析

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Xxx.class); public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { //保存一个读取注解的Bean 定义读取器,并将其设置到容器中 private final AnnotatedBeanDefinitionReader reader; //保存一个扫描指定类路径中注解Bean 定义的扫描器,并将其设置到容器中 private final ClassPathBeanDefinitionScanner scanner; /** * 默认构造函数,初始化一个空容器,容器不包含任何Bean 信息,需要在稍后通过调用其register() * 方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean 的载入、解析和注册过程 * Create a new AnnotationConfigApplicationContext that needs to be populated * through {@link #register} calls and then manually {@linkplain #refresh refreshed}. */ public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } public AnnotationConfigApplicationContext(Class<?>... componentClasses) { //调用默认无参构造器,主要初始化AnnotatedBeanDefinitionReader // 以及路径扫描器ClassPathBeanDefinitionScanner this(); //把传入的Class进行注册,Class既可以有@Configuration注解,也可以没有@Configuration注解 //如何注册委托给了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法进行注册 // 包装传入的Class 生成 BeanDefinition , 注册到BeanDefinitionRegistry register(componentClasses); refresh(); } @Override public void register(Class<?>... componentClasses) { Assert.notEmpty(componentClasses, "At least one component class must be specified"); this.reader.register(componentClasses); } }

AnnotatedBeanDefinitionReader

发现 AnnotatedBeanDefinitionReader没有继承和实现任何类与接口,即该类并不属于BeanDefinitionReader的体系,而是专门用于处理注解相关的BeanDefinition的配置读入,这样做可以用于区分出注解和其他配置方式的不同。

 

注解的处理逻辑相对更清晰,在上一文分析了XML相关的解析逻辑之后,理解注解也会相对容易一些。

深入this.reader.register(componentClasses)方法,进入AnnotatedBeanDefinitionReader类

public class AnnotatedBeanDefinitionReader { //还是委托BeanDefinitionRegistry将AnnotatedBeanDefinition实例注入到IOC容器中 private final BeanDefinitionRegistry registry; public void register(Class<?>... componentClasses) { for (Class<?> componentClass : componentClasses) { registerBean(componentClass); } } public void registerBean(Class<?> beanClass) { doRegisterBean(beanClass, null, null, null, null); } }

doRegisterBean()方法真正的注册方法,继续深入

public class AnnotatedBeanDefinitionReader { private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); //此段代码用于处理 Conditional 注解,在特定条件下阻断 bean 的注册 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } //用来创建 bean 的 supplier,会替代掉 bean 本身的创建方法 //instanceSupplier 一般情况下为 null abd.setInstanceSupplier(supplier); //此行代码处理 scope 注解,本例中 scope 是默认值 singleton ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); //获取beanName String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); //特定注解解析,本例中均没传入dependsOn,LazyInit这些注解 //这些注解就和<bean>标签里面的属性作用是一样的 AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); //本例中 qualifiers 传入的是 null,qualifiers就是用来决定接口的实现类的 if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } //主要提供对BeanDefinition的一些定制化操作 if (customizers != null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } //用 BeanDefinitionHolder 包装 BeanDefinition BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); //此行代码与动态代理和 scope 注解有关,主要看看是否依照Spring的scope生成动态代理对象 // 但是在本案例中没有做任何操作,只是返回了传入的 definitionHolder definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //向容器注册扫描到的Bean BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); } }
  • 1、将类转换为AnnotatedGenericBeanDefinition。
  • 2、调用conditionEvaluator的shouldSkip判断是否需要过滤,shouldSkip方法中先判断类上是否有Conditional注解,只处理有Conditional注解或其衍生注解的情况。
  • 3、获取beanName,如果我们设置了value则取其值,如果没有设置,底层上是调用JDK的Introspector.decapitalize方法,比如类名是HelloWorld,则对应的beanName是helloWorld。
  • 4、调用AnnotationConfigUtils.processCommonDefinitionAnnotations,获取Lazy、Primary、DependsOn等注解的值。
  • 5、最后调用BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry)将这个BeanDefinition注册到registry中,这里的注册和xml方式的注册一模一样。

使用AnnotationConfigUtils的processCommonDefinitionAnnotations方法处理注解Bean定义类中通用的注解

二、不是被@Configuration标记的Bean(即普通的业务Bean)的资源定位、加载、解析、注册分析

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { public AnnotationConfigApplicationContext(Class<?>... componentClasses) { //调用默认无参构造器,主要初始化AnnotatedBeanDefinitionReader // 以及路径扫描器ClassPathBeanDefinitionScanner this(); //把传入的Class进行注册,Class既可以有@Configuration注解,也可以没有@Configuration注解 //如何注册委托给了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法进行注册 // 包装传入的Class 生成 BeanDefinition , 注册到BeanDefinitionRegistry register(componentClasses); //@Controller、@Service、@Component、@Repository标记的类在此方法被注册进IOC容器 refresh(); } }

针对普通的业务Bean,即@Controller、@Service、@Component、@Repository标记的类是在AnnotationConfigApplicationContext构造函数中的refresh()方法的时候才会被注册进IOC容器,这和XML解析方式一样是调用的AbstractApplicationContext中的refresh()方法。

  • XML配置方式的解析配置并注册BeanDefinition实例时候,是调用的obtainFreshBeanFactory()方法。
  • 而注解方式是调用的invokeBeanFactoryPostProcessors(beanFactory)方法,在容器调用其后置处理器的时候会触发对普通的BeanDefinition的注册。
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { /** * 加载或刷新一个持久化的配置,可能是XML文件、属性文件或关系数据库模式。 * 由于这是一种启动方法,如果失败,应该销毁已经创建的单例,以避免悬空资源。 * 换句话说,在调用该方法之后,要么全部实例化,要么完全不实例化。 * @throws BeansException 如果bean工厂无法初始化,则抛出 BeansException 异常 * @throws IllegalStateException 如果已经初始化且不支持多次刷新,则会抛出 IllegalStateException 异常 */ @Override public void refresh() throws BeansException, IllegalStateException { // 给容器refresh加锁,避免容器处在refresh阶段时,容器进行了初始化或者销毁的操作 synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识,具体方法 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从 //子类的refreshBeanFactory()方法启动,里面有抽象方法 //针对xml配置,最终创建内部容器,该容器负责 Bean 的创建与管理,此步会进行BeanDefinition的注册 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 注册一些容器中需要的系统Bean.例如classloader,beanfactoryPostProcessor等 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //允许容器的子类去注册postProcessor ,钩子方法 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 激活在容器中注册为bean的BeanFactoryPostProcessors //对于注解容器,org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry //方法扫描应用中所有BeanDefinition并注册到容器之中 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注册拦截bean创建过程的BeanPostProcessor registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 找到“messageSource”的Bean提供给ApplicationContext使用, // 使得ApplicationContext具有国际化能力。 initMessageSource(); // Initialize event multicaster for this context. // 初始化ApplicationEventMulticaster该类作为事件发布者, // 可以存储所有事件监听者信息,并根据不同的事件,通知不同的事件监听者。 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 预留给 AbstractApplicationContext 的子类用于初始化其他特殊的 bean, // 该方法需要在所有单例 bean 初始化之前调用 // 比如Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource) onRefresh(); // Check for listener beans and register them. // 注册监听器(检查监听器的bean并注册它们) registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //设置自定义的类型转化器ConversionService, // 设置自定义AOP相关的类LoadTimeWeaverAware, // 清除临时的ClassLoader // ,实例化所有的类(懒加载的类除外) finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // 初始化容器的生命周期事件处理器,(默认使用DefaultLifecycleProcessor),调用扩展了SmartLifecycle接口的start方法 // 当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法) // 并发布容器刷新完毕事件ContextRefreshedEvent给对应的事件监听者 finishRefresh(); } 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. //销毁已创建的Bean destroyBeans(); // Reset 'active' flag. //取消refresh操作,重置容器的同步标识 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... // 重置Spring内核中的共用的缓存,因为我们可能再也不需要单例bean的元数据了…… resetCommonCaches(); } } } }

invokeBeanFactoryPostProcessors(beanFactory)方法中

  • 该方法会实例化和调用所有 BeanFactoryPostProcessor(包括其子类 BeanDefinitionRegistryPostProcessor)。
  • BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。
  • BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。

 

注:这边的 “常规 BeanFactoryPostProcessor” 主要用来跟 BeanDefinitionRegistryPostProcessor 区分。

 

接着深入invokeBeanFactoryPostProcessors(beanFactory)方法

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { /** * 实例化并调用所有已注册的BeanFactoryPostProcessor 的 bean,如果已给出顺序,请按照顺序。 * 必须在单实例实例化之前调用。 * Instantiate and invoke all registered BeanFactoryPostProcessor beans, * respecting explicit order if given. * <p>Must be called before singleton instantiation. */ protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 1.getBeanFactoryPostProcessors(): 拿到当前应用上下文beanFactoryPostProcessors变量中的值 // 2.invokeBeanFactoryPostProcessors: 实例化并调用所有已注册的BeanFactoryPostProcessor PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // 如何找到一个LoadTimeWeaver,那么就准备将后置处理器“织入”bean工厂 // (例如,一个 @Bean 方法通过ConfigurationClassPostProcessor来注册) // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } } }

1、拿到当前应用上下文 beanFactoryPostProcessors 变量中的值。

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { //应用于刷新的 BeanFactoryPostProcessors,这个List用于存放Bean工厂处理器(BeanFactoryPostProcessor) private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>(); //返回将应用到内部BeanFactory的BeanFactoryPostProcessors列表 public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() { return this.beanFactoryPostProcessors; } }

这边 getBeanFactoryPostProcessors() 会拿到当前应用上下文中已经注册的 BeanFactoryPostProcessor,在默认情况下,this.beanFactoryPostProcessors 是返回空的。

如何添加自定义 BeanFactoryPostProcessor 到 this.beanFactoryPostProcessors 变量中?

新建一个 ApplicationContextInitializer 的实现类 SpringApplicationContextInitializer ,并在 initialize 方法中写我们的逻辑。

public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext applicationContext) { FirstBeanDefinitionRegistryPostProcessor firstBeanDefinitionRegistryPostProcessor = new FirstBeanDefinitionRegistryPostProcessor(); // 将自定义的firstBeanDefinitionRegistryPostProcessor添加到应用上下文中 applicationContext.addBeanFactoryPostProcessor(firstBeanDefinitionRegistryPostProcessor); // ...自定义操作 System.out.println("MyApplicationContextInitializer#initialize"); } }

1、Spring实现方式

将 SpringApplicationContextInitializer 作为初始化参数 contextInitializerClasses 配置到 web.xml 中。

<context-param> <param-name>contextInitializerClasses</param-name> <param-value> com.yibo.spring.MyApplicationContextInitializer </param-value> </context-param>

这样,在启动应用时,FirstBeanDefinitionRegistryPostProcessor 就会被添加到 this.beanFactoryPostProcessors 中。

2、SpringBoot方式

2.1、mian函数中添加

@SpringBootApplication public class MySpringBootApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(MySpringBootApplication.class); application.addInitializers(new MyApplicationContextInitializer()); application.run(args); } }

2.2、配置文件中配置

context.initializer.classes= com.yibo.spring.MyApplicationContextInitializer

2.3、SpringBoot的SPI扩展---META-INF/spring.factories中配置

在项目下的resources下新建META-INF文件夹,文件夹下新建spring.factories文件

org.springframework.context.ApplicationContextInitializer= com.yibo.spring.MyApplicationContextInitializer

给 MyApplicationContextInitializer 加上Order注解:我们指定其拥有最高的排序级别。(越高越早执行)

@Order(Ordered.HIGHEST_PRECEDENCE) public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext applicationContext) { FirstBeanDefinitionRegistryPostProcessor firstBeanDefinitionRegistryPostProcessor = new FirstBeanDefinitionRegistryPostProcessor(); // 将自定义的firstBeanDefinitionRegistryPostProcessor添加到应用上下文中 applicationContext.addBeanFactoryPostProcessor(firstBeanDefinitionRegistryPostProcessor); // ...自定义操作 System.out.println("MyApplicationContextInitializer#initialize"); } }

2、实例化并调用所有已注册的 BeanFactoryPostProcessor

深入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())

final class PostProcessorRegistrationDelegate { /** * 调用BeanFactoryPostProcessor * 主要是分情况处理不同类型的BeanFactoryPostProcessors。 * BeanFacotryPostProcessors主要分为两类,一类是BeanDefinitionRegistry的BeanFactoryPostProcessor,另外一类是常规的BeanFactoryPostProcessor。 * 优先处理前者。同时,这两种后置处理器又被分为从参数里传入和从容器里获取的,最终要将从参数里获取的和从容器里获取的合并在一起。 * 合并的时候又分为实现了PriorityOrder和普通Order以及没有实现这两个接口的,实现了PriorityOrdered的先执行, * 同时是按照PriorityOrdered顺序执行的,其次再到Order,按照Order执行,最后才是没实现这两个接口的, * 先执行完BeanDefinitionRegistryPostProcessor的invokeBeanDefinitionRegistryPostProcessors方法, * 再对BeanDefinitionRegistryPostProcessor执行invokeBeanFactoryPostProcessors方法, * 之后再对常规的BeanFacotryPostProcessors执行invokeBeanFactoryPostProcessors方法 * @参数 beanFactory 应用上下文的 BeanFactory 实例 * @参数 beanFactoryPostProcessors 应用上下文指定要执行的 BeanFactoryPostProcessor **/ public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. // 如果有BeanDefinitionRegistryPostProcessor的话优先执行 Set<String> processedBeans = new HashSet<>(); // 1.判断beanFactory是否为BeanDefinitionRegistry,beanFactory为DefaultListableBeanFactory, // 而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,因此这边为true if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; // 用于存放普通的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); // 用于存放BeanDefinitionRegistryPostProcessor List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); // 2.首先处理入参中的beanFactoryPostProcessors // 遍历所有的beanFactoryPostProcessors, 将BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor区分开 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { // 2.1 如果是BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; // 2.1.1 直接执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法 registryProcessor.postProcessBeanDefinitionRegistry(registry); // 2.1.2 添加到registryProcessors(用于最后执行postProcessBeanFactory方法) registryProcessors.add(registryProcessor); } else { // 2.2 否则,只是普通的BeanFactoryPostProcessor // 2.2.1 添加到regularPostProcessors(用于最后执行postProcessBeanFactory方法) regularPostProcessors.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. // 用于保存本次要执行的BeanDefinitionRegistryPostProcessor List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. // 3.调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类 // 3.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的Bean的beanName String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // 3.2 遍历postProcessorNames for (String ppName : postProcessorNames) { // 3.3 校验是否实现了PriorityOrdered接口 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 3.4 获取ppName对应的bean实例, 添加到currentRegistryProcessors中, // beanFactory.getBean: 这边getBean方法会触发创建ppName对应的bean对象, 目前暂不深入解析 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); // 3.5 将要被执行的加入processedBeans,避免后续重复执行 processedBeans.add(ppName); } } // 3.6 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序) sortPostProcessors(currentRegistryProcessors, beanFactory); // 3.7 添加到registryProcessors(用于最后执行postProcessBeanFactory方法) registryProcessors.addAll(currentRegistryProcessors); // 3.8 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 3.9 执行完毕后, 清空currentRegistryProcessors currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. // 4.调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类(过程跟上面的步骤3基本一样) // 4.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类, 这边重复查找是因为执行完上面的BeanDefinitionRegistryPostProcessor, // 可能会新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找 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); // 4.2 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. // 5.最后, 调用所有剩下的BeanDefinitionRegistryPostProcessors boolean reiterate = true; while (reiterate) { reiterate = false; // 5.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 5.2 跳过已经执行过的 if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); // 5.3 如果有BeanDefinitionRegistryPostProcessor被执行, 则有可能会产生新的BeanDefinitionRegistryPostProcessor, // 因此这边将reiterate赋值为true, 代表需要再循环查找一次 reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); // 5.4 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. // 6.调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor) invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); // 7.最后, 调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的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! // 到这里 , 入参beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已经全部处理完毕, // 下面开始处理容器中的所有BeanFactoryPostProcessor // 8.找出所有实现BeanFactoryPostProcessor接口的类 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. // 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); // 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanName List<String> orderedPostProcessorNames = new ArrayList<>(); // 用于存放普通BeanFactoryPostProcessor的beanName List<String> nonOrderedPostProcessorNames = new ArrayList<>(); // 8.1 遍历postProcessorNames, 将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开 for (String ppName : postProcessorNames) { // 8.2 跳过已经执行过的 if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 8.3 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { // 8.4 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName orderedPostProcessorNames.add(ppName); } else { // 8.5 添加剩下的普通BeanFactoryPostProcessor的beanName nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. // 9.调用所有实现PriorityOrdered接口的BeanFactoryPostProcessor // 9.1 对priorityOrderedPostProcessors排序 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); // 9.2 遍历priorityOrderedPostProcessors, 执行postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. // 10.调用所有实现Ordered接口的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { // 10.1 获取postProcessorName对应的bean实例, 添加到orderedPostProcessors, 准备执行 orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } // 10.2 对orderedPostProcessors排序 sortPostProcessors(orderedPostProcessors, beanFactory); // 10.3 遍历orderedPostProcessors, 执行postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. // 11.调用所有剩下的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { // 11.1 获取postProcessorName对应的bean实例, 添加到nonOrderedPostProcessors, 准备执行 nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } // 11.2 遍历nonOrderedPostProcessors, 执行postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... // 12.清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType), // 因为后处理器可能已经修改了原始元数据,例如, 替换值中的占位符... beanFactory.clearMetadataCache(); } }

调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)进行BeanDefinition的注册

private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } }

上一步每一个BeanDefinitionRegistryPostProcessor都会调用postProcessBeanDefinitionRegistry(registry)进行处理,继续深入该方法

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { int 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); } }

通过上面发现,BeanDefinition实例的注册是通过ConfigurationClassPostProcessor类的后置处理方法processConfigBeanDefinitions(registry);方法来处理。

继续深入processConfigBeanDefinitions(registry)方法

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware { public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { //1.初始化BeanDefinitionHolder集合 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); //2.所有已经注册的bean String[] candidateNames = registry.getBeanDefinitionNames(); //3.遍历已注册的bean数组 for (String beanName : candidateNames) { //得到BeanDefinition实例 BeanDefinition beanDef = registry.getBeanDefinition(beanName); if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { //如果BeanDefinition 中的configurationClass 属性为full 或者lite ,则意味着已经处理过了,直接跳过 if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { //带有@Configuration注解的bean添加到集合中 // 判断对应bean是否为配置类,如果是,则加入到configCandidates configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // Return immediately if no @Configuration classes were found if (configCandidates.isEmpty()) { //两种都不满足,配置类已经被处理了 return; } // Sort by previously determined @Order value, if applicable // 对configCandidates 进行 排序,按照@Order 配置的值进行排序 configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing application context // 如果BeanDefinitionRegistry 是SingletonBeanRegistry 的子类的话, // 由于我们当前传入的是DefaultListableBeanFactory,它是 // SingletonBeanRegistry 的子类。因此会将registry强转为SingletonBeanRegistry SingletonBeanRegistry 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) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } //web应用为StandardServletEnvironment if (this.environment == null) { this.environment = new StandardEnvironment(); } // Parse each @Configuration class //初始化一个ConfigurationClassParser解析器,可以解析@Congiguration配置类 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); //List转成Set Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); //初始化一个已经解析的HashSet Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); //循环解析,直到candidates为空 do { //核心:解析 parser.parse(candidates); //主要校验配置类不能使用final修饰符(CGLIB代理是生成一个子类,因此原先的类不能使用final修饰) //if (this.getMetadata().isAnnotated(Configuration.class.getName()) && this.getMetadata().isFinal()) parser.validate(); //排除已处理过的配置类 Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content //读取模型并根据其内容创建bean定义 if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } //2.加载bean定义信息,主要实现将@Configuration @Import @ImportResource @ImportRegistrar注册为bean this.reader.loadBeanDefinitions(configClasses); //将configClasses加入到已解析alreadyParsed中 alreadyParsed.addAll(configClasses); //清空已处理的配置类 candidates.clear(); //再次获取容器中bean定义数量 如果大于 之前获取的bean定义数量,则说明有新的bean注册到容器中,需要再次解析 //getBeanDefinitionCount()取得是registry.beanDefinitionMap.size() if (registry.getBeanDefinitionCount() > candidateNames.length) { //容器中新的所有已注册的bean(包括老的) String[] newCandidateNames = registry.getBeanDefinitionNames(); //容器中老的已注册的bean(已经解析了) Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); //用来存储已经解析的类 Set<String> alreadyParsedClasses = new HashSet<>(); //循环遍历把已解析的类放到alreadyParsedClasses中 for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } //循环遍历新的所有已注册的bean,排除老的已解析的,再过滤是否是配置类带有@Configuration,并且没有解析过,添加到candidates中, //下一次可以再处理解析 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 classes if (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(); } } }

parser.parse(candidates)对配置类的解析

class ConfigurationClassParser { private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler(); public void parse(Set<BeanDefinitionHolder> configCandidates) { //循环遍历需要处理的配置类 for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); //根据BeanDefinition实例判断调用哪个,其实最后还是调用 //核心方法:processConfigurationClass(ConfigurationClass configClass) try { if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex); } } //字面理解:处理延迟导入的javabean //parse方法,把被处理的类实现DeferredImportSelector接口,加入deferredImportSelectors集合中, //处理deferredImportSelectors集合种类 this.deferredImportSelectorHandler.process(); } }

继续深入其中的一个parse()方法

class ConfigurationClassParser { protected final void parse(@Nullable String className, String beanName) throws IOException { Assert.notNull(className, "No bean class name for configuration class bean definition"); MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className); processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER); } protected final void parse(Class<?> clazz, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER); } protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER); } }

parse调用核心方法processConfigurationClass(ConfigurationClass configClass)解析

class ConfigurationClassParser { protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException { //检查当前解析的配置bean是否包含Conditional注解,如果不包含则不需要跳过 // 如果包含了则进行match方法得到匹配结果,如果是符合的并且设置的配置解析策略是解析阶段不需要调过 if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return; } //在这里处理Configuration重复import //如果同一个配置类被处理两次,两次都属于被import的则合并导入类,返回。如果配置类不是被导入的,则移除旧使用新的配置类 ConfigurationClass existingClass = this.configurationClasses.get(configClass); if (existingClass != null) { if (configClass.isImported()) { if (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. 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 { sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); } while (sourceClass != null); // 添加到ConfigurationClassParser的configurationClasses中 this.configurationClasses.put(configClass, configClass); } }

递归解析,调用doProcessConfigurationClass方法,终于到了解析的地方,继续深入

class ConfigurationClassParser { protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // Recursively process any member (nested) classes first 处理内部类 processMemberClasses(configClass, sourceClass, filter); } // Process any @PropertySource annotations // 处理@PropertySource注解 for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // Process any @ComponentScan annotations // 处理@ComponentScan注解 Set<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) { // The config class is annotated with @ComponentScan -> perform the scan immediately Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed //遍历扫描到的配置类进行递归解析 for (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()); } } } } // Process any @Import annotations // 处理@Import注解 processImports(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"); // 遍历配置的locations,加入到configClass 中的ImportedResource for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } // Process individual @Bean methods // 处理@Bean修饰的方法 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces // 处理接口定义的方法 processInterfaces(configClass, sourceClass); // Process superclass, if any if (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 recurse return sourceClass.getSuperClass(); } } // No superclass -> processing is complete return null; } }

解析doProcessConfigurationClass方法,总结一下:

  • 1、处理内部类
  • 2、处理@PropertySource注解
  • 3、处理@ComponentScan注解
  • 4、处理@Import注解
  • 5、处理@ImportResource注解
  • 6、处理@Bean修饰的方法
  • 7、处理接口定义的方法
  • 8、处理父类

1、处理内部类(递归解析)

class ConfigurationClassParser { /** * Register member (nested) classes that happen to be configuration classes themselves. * 处理内部类 */ private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { //读取配置类中所有成员类 Collection<SourceClass> memberClasses = sourceClass.getMemberClasses(); if (!memberClasses.isEmpty()) { List<SourceClass> candidates = new ArrayList<>(memberClasses.size()); for (SourceClass memberClass : memberClasses) { //过滤出配置类 if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) && !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) { candidates.add(memberClass); } } //根据Order进行排序 OrderComparator.sort(candidates); //遍历 for (SourceClass candidate : candidates) { //出现配置类循环导入,直接报错 if (this.importStack.contains(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack)); } else { //将配置类入栈 this.importStack.push(configClass); try { //处理配置类 processConfigurationClass(candidate.asConfigClass(configClass), filter); } finally { //解析完出栈 this.importStack.pop(); } } } } } }

2、处理@PropertySource注解

如果配置类上有@PropertySource注解,则解析加载properties文件,并将属性添加到Spring上下文中。 深入processPropertySource(propertySource)方法

class ConfigurationClassParser { private void processPropertySource(AnnotationAttributes propertySource) throws IOException { String name = propertySource.getString("name"); if (!StringUtils.hasLength(name)) { name = null; } 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 ex) { // Placeholders not resolvable or resource not found when trying to open it if (ignoreResourceNotFound) { if (logger.isInfoEnabled()) { logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage()); } } else { throw ex; } } } } private void addPropertySource(PropertySource<?> propertySource) { String name = propertySource.getName(); MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources(); //如果存在同名的PropertySource, // 则使用CompositePropertySource替换原来的PropertySource, // 而CompositePropertySource中包含了所有的PropertySource if (this.propertySourceNames.contains(name)) { // We've already added a version, we need to extend it PropertySource<?> existing = propertySources.get(name); if (existing != null) { PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ? ((ResourcePropertySource) propertySource).withResourceName() : propertySource); if (existing instanceof CompositePropertySource) { //将新的PropertySource添加到第一个,使用时在该组中最后一个使用。 ((CompositePropertySource) existing).addFirstPropertySource(newSource); } else { if (existing instanceof ResourcePropertySource) { existing = ((ResourcePropertySource) existing).withResourceName(); } CompositePropertySource composite = new CompositePropertySource(name); composite.addPropertySource(newSource); composite.addPropertySource(existing); propertySources.replace(name, composite); } return; } } /** * 如果没有同名的PropertySource,当只有一个的时候,直接添加到propertySources中 * 否则将新的PropertySource添加到除systemProperties * systemEnvironment变量紧接着的第一个(意思就是后添加的后使用,但是如果他们存在同名的属性,后使用的PropertySource会覆盖先使用的) */ if (this.propertySourceNames.isEmpty()) { propertySources.addLast(propertySource); } else { /** * propertySourceNames中存放的是自定义的PropertySource name,不包含systemProperties systemEnvironment * 因此每次添加的新PropertySource都是在列表中的第三个(得出此结论的前提框架不在添加其他默认的PropertySource) */ String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1); propertySources.addBefore(firstProcessed, propertySource); } this.propertySourceNames.add(name); } }

3、处理@ComponentScan注解

获取配置类上的@ComponentScan注解,判断是否需要跳过。循环所有的ComponentScan,立即执行扫描。

// Process any @ComponentScan annotations // 处理@ComponentScan注解 Set<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) { // The config class is annotated with @ComponentScan -> perform the scan immediately Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed //遍历扫描到的配置类进行递归解析 for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } //检验扫描获得的BeanDefinition中是否有配置类,如果有配置类,这里的配置类包括FullConfigurationClass和LiteConfigurationClass。 //(也就是说只要有@Configuration、@Component、@ComponentScan、@Import、@ImportResource和@Bean中的其中一个注解),则递归调用parse方法,进行解析。 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } }

继续深入分析

Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); class ComponentScanAnnotationParser { private final Environment environment; private final ResourceLoader resourceLoader; private final BeanDefinitionRegistry registry; public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { //根据@ComponentScan的useDefaultFilters值来构建一个ClassPathBeanDefinitionScanner //默认为true 如果为true 会注册一些默认的注解过滤器,例如@Component @ManagedBean 和 @Named ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); //类名生成器,默认为BeanNameGenerator接口 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass); //为scanner设置类名生成器,默认为AnnotationBeanNameGenerator 如果不填则为类名且首字母小写 scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass)); ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); //scopedProxy默认为DEFAULT if (scopedProxyMode != ScopedProxyMode.DEFAULT) { scanner.setScopedProxyMode(scopedProxyMode); } else { //scopeResolver默认为AnnotationScopeMetadataResolver Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver"); scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass)); } //设置资源匹配器 默认为**/*.class 即所有class scanner.setResourcePattern(componentScan.getString("resourcePattern")); //找到所有的设置的filter 默认为空 for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addIncludeFilter(typeFilter); } } //找到所有排除的filter ,springboot默认有TypeExcludeFilter和AutoConfigurationExcludeFilter for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addExcludeFilter(typeFilter); } } //是否懒加载 默认为false 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); } //如果有basePackageClasses则添加 默认为null for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) { basePackages.add(ClassUtils.getPackageName(clazz)); } //如果上述的全部为空 则添加声明类的所在包 //这也就是为何@SpringbootApplication默认只解析其所在的包下面的所有的类,其上级包没法解决 if (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); } //将传入的类本身排除掉 scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { @Override protected boolean matchClassName(String className) { return declaringClass.equals(className); } }); //进行扫描 return scanner.doScan(StringUtils.toStringArray(basePackages)); } }

这个方法很长,但内容很简单,无非就是挨个解析@ComponentScan的值并将其设置到ClassPathBeanDefinitionScanner中,然后调用scanner的解析方法,这儿有两点需要注意

  • 1、默认的includeFilter中加入了@Component注解,这个非常重要
  • 2、如果注解中没有找到任何可用的basePackage,那么会默认使用传入类的package作为basePackage,而这儿第一次进来的一般为主启动类,所以@springbootApplication之所以默认是解析其类所在的包下所有的类的缘由就在于此。

然后我们接着看doScan方法

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider { private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE; private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver(); protected Set<BeanDefinitionHolder> doScan(String... basePackages) { //做下判空 Assert.notEmpty(basePackages, "At least one base package must be specified"); //创建返回set Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); //迭代每个basePackage for (String basePackage : basePackages) { //找到basePackage下所有的配置类 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); //处理这次找到的所有配置类 for (BeanDefinition candidate : candidates) { //获取其Scope信息,也就是分析其@Scope注解 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); //设置其scope candidate.setScope(scopeMetadata.getScopeName()); //这儿会获取名字,如果没有默认为其类名且首字母小写 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); //如果配置类的BeanDefinition继承了AbstractBeanDefinition if (candidate instanceof AbstractBeanDefinition) { //则为这个candidate根据刚才初始化时构建的beanDefinitionDefaults来设置BeanDefinition一些属性, //例如是否懒加载,自动装配模型等 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } //如果配置类 的BeanDefinition实现了AnnotatedBeanDefinition接口 //例如有@Lazy @Primary @DependsOn @Role @Description等注解 if (candidate instanceof AnnotatedBeanDefinition) { //那么就对其每个注解进行特定的处理 例如Lazy设置懒加载 // 例如Primary设置该类为主要类(例如一个接口有多个实现时,某个实现类加上这个就可以直接使用@Autowire注解不会报错) AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //检查一下该配置类是否在registray中已存在。为true则代表无冲突,否则会报异常 //例如两个类名一样且都使用@Component注解没有指定姓名就会报错这儿 if (checkCandidate(beanName, candidate)) { //如果没问题则构造一个BeanDefinitionHolder BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); //这儿是根据scope信息来判定是否需要需要生成代理 默认不生成 //如果要生成可以为配置类加上@Scope(proxyMode = ScopedProxyMode.DEFAULT) 即可//只要不为ScopedProxyMode.NO(默认属性)即可 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //将该配置类注入到spring的registry中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; } }

这个方法主要就是根据basePackage找到所有的配置类并创建BeanDefinition返回,然后为BeanDefinition设置一些必要的属性,最后根据特定的注解做一些特殊的判断即可。最后这些配置类代表的BeanDefinitionHolder 会被添加到spring的regitry中,在后面实例化的时候将会有很大的作用。

 

那我们还是接着看下basePackage下的Bean是如何被找到的,我们接着看findCandidateComponents方法。

public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware { public Set<BeanDefinition> findCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); } } private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { //找到解析的路径匹配规则 resourcePattern默认为**/*.class 即所有的class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; //根据路径去循环递归查找路径所包含的每一个class文件 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } //循环处理每个可读的class文件 if (resource.isReadable()) { try { //读取文件的元数据 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); //如果文件在includeFilter中 且没有包含在excludeFilters中 则说明是我们需要加入到容器中的配置类 if (isCandidateComponent(metadataReader)) { //新建ScannedGenericBeanDefinition (注意其实现了AnnotatedBeanDefinition接口,且集成了AbstractBeanDefinition类) ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } //返回 return candidates; } }

这个方法就很简单了,系统解析了路径,并找到路径下所有的class文件,那么spring怎么知道哪些是需要加载配置的呢,这时在上面着重让大家记住的includeFilter就起作用了,由于其加入了@Component注解的支持,我们看这个isCandidateComponent方法。

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; }

看了这个方法相信大家就了然了,只有includeFilter为true才会返回true,这儿还有点需要注意的是isConditionMatch,这个处理的是@Conditional系列的注解,用来判定是否满足加载配置的条件。如果不满足则不必加载,会返回false。

来看component-scan的几个属性

  • basePackages:Spring将扫描的基础package名,Spring会扫描该包以及其子孙包下的所有类。

  • useDefaultFilters:默认为true,此时Spring扫描类时发现如果其被标注为 @Component、@Repository、@Service、@Controller则自动实例化为bean并将其添加到上下文中,如果设置为false,即使将其标注为@Component或者其他,Spring都会忽略。

  • includeFilters:指定扫描时需要实例化的类型,我们可以从名字看到这是一个Filter,你可以自己定义该Filter,Spring为我们提供了一套方便的实现,我们可以根据标注、类、包等相关信息决定当扫描到该类时是否需要实例化该类,需要注意的是如果你仅仅想扫描如@Controller不仅要加includeFilters,还需要将useDefaultFilters设置为false

  • excludeFilter:指定扫描到某个类时需要忽略它,实现和上一个Filter一样,区别只是如果Filter匹配,Spring会忽略该类。

这样includeFilters以及excludeFilterF的行为就很清楚了,Spring每扫描一个类,都会经过includeFilters以及excludeFilters,如果某个Filter匹配,就执行相应的操作(实例化或者忽略)。

接着回到doScan方法中,该方法最后会调用registerBeanDefinition(definitionHolder, this.registry)方法,将扫描出来的BeanDefinition注册到到spring的容器中

//将该配置类注入到spring的registry中 registerBeanDefinition(definitionHolder, this.registry); public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider { protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) { BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry); } } public abstract class BeanDefinitionReaderUtils { public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. // 使用beanName做唯一标识注册 String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. // 注册所有的别名 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } } }
  • 最终将解析出来的BeanDefinition封装到BeanDefinitionHolder中,由BeanDefinitionReaderUtils的registerBeanDefinition方法将BeanDefinition注册到Spring IOC容器中。
  • 最终调用DefaultListableBeanFactory类的registerBeanDefinition方法将beanDefinition注册到beanDefinitionMap中。

4、处理@Import注解

processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

processImports方法负责对@Import注解进行解析。configClass是配置类,sourceClass又是通过configClass创建的,getImports(sourceClass)从sourceClass获取所有的@Import注解信息

class ConfigurationClassParser { private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) { if (importCandidates.isEmpty()) { return; } //循环导入直接报错 if (checkForCircularImports && isChainedImportOnStack(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack)); } else { //推入栈 this.importStack.push(configClass); try { //循环遍历 for (SourceClass candidate : importCandidates) { //对import的内容进行分类 // import导入实现ImportSelector接口的类 if (candidate.isAssignable(ImportSelector.class)) { // Candidate class is an ImportSelector -> delegate to it to determine imports Class<?> candidateClass = candidate.loadClass(); // 反射创建这个类的实例对象 ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class, this.environment, this.resourceLoader, this.registry); //是否有实现相关Aware接口,如果有,这调用相关方法 Predicate<String> selectorFilter = selector.getExclusionFilter(); // 延迟加载的ImportSelector if (selectorFilter != null) { exclusionFilter = exclusionFilter.or(selectorFilter); } if (selector instanceof DeferredImportSelector) { // 延迟加载的ImportSelector先放到List中,延迟加载 this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector); } else { // 普通的ImportSelector ,执行其selectImports方法,获取需要导入的类的全限定类名数组 String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter); // 递归调用 processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false); } } // 是否为ImportBeanDefinitionRegistrar else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { // Candidate class is an ImportBeanDefinitionRegistrar -> // delegate to it to register additional bean definitions Class<?> candidateClass = candidate.loadClass(); ImportBeanDefinitionRegistrar registrar = ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry); // 添加到成员变量 configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else { // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> // process it as an @Configuration class // 普通 @Configuration class this.importStack.registerImport( currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); // 解析导入的@Configuration class 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(); } } } }

5、处理@ImportResource注解

@ImportResource注解可以导入xml配置文件。

// Process any @Import annotations // 处理@Import注解 processImports(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"); // 遍历配置的locations,加入到configClass 中的ImportedResource for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); //把配置项提取出来,跟reader一起放入configClass的map中, //接下来会在ConfigurationClassPostProcessor类中processConfigBeanDefinitions方法中,解析完, //this.reader.loadBeanDefinitions(configClasses)这方法会对@import处理(对ImportBeanDefinitionRegistrars的处理) configClass.addImportedResource(resolvedResource, readerClass); } }

6、处理@Bean修饰的方法

// Process individual @Bean methods // 处理@Bean修饰的方法 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { //添加到configClass的beanMethods集合中,接下来,会在this.reader.loadBeanDefinitions(configClasses)这方法 //得到处理 configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); }

7、处理接口定义的方法

// Process default methods on interfaces // 处理接口定义的方法 processInterfaces(configClass, sourceClass);

8、处理父类

// Process superclass, if any // 8.如果有父类则递归读取父类 if (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 recurse return sourceClass.getSuperClass(); } } // No superclass -> processing is complete // 没有父类直接返回 return null;

参考: https://www.abboke.com/jsh/2019/0628/4154.html

https://www.cnblogs.com/ZhuChangwu/p/11674684.html

https://blog.csdn.net/tuoni123/article/details/79976105

https://www.cnblogs.com/TimeSay/p/10874476.html

https://zhuanlan.zhihu.com/p/83473498

https://www.cnblogs.com/hello-shf/p/10987360.html

https://www.cnblogs.com/duanxz/p/11239291.html

https://www.cnblogs.com/mufeng07/p/12165616.html

https://www.cnblogs.com/mufeng07/p/12172549.html

https://www.cnblogs.com/hetutu-5238/p/12378432.html

网友评论