Spring Bean 的生命周期有4个阶段:Bean 定义、Bean 初始化、Bean 生存期、Bean 销毁。因为“Bean 生存期”阶段就是程序启动后我们使用 Bean 的过程,所以不需要介绍。这篇博客介绍的是“Bean 定义”阶段。
源码版本:SpringBoot 2.3.0,Spring 5.2.6
概述 “Bean定义”是 Spring Bean 的生命周期的第一个阶段,这个阶段里会根据启动类上的注解 @ComponentScan 指定的包路径(默认是当前包及其子包)扫描,把 Bean 定义信息保存到 IoC 容器中,待“Bean 初始化”阶段使用。
SpringBoot Web 应用使用的 IoC 容器为AnnotationConfigServletWebServerApplicationContext,这个容器包含一个属性:beanFactory = DefaultListableBeanFactory 。所有 Bean 定义信息就是保存到 DefaultListableBeanFactory 的成员 Map<String, BeanDefinition> beanDefinitionMap 中。BeanDefinidition 是用来记录 Bean 定义信息的接口,子类有 RootBeanDefinition、AnnotatedGenericBeanDefinition、ScannedGenericBeanDefinition 等。
真正开始注册 Bean 定义信息的时候是容器刷新的时候,即发生在 AbstractApplicationContext.refresh() 中。下面先看看容器刷新前为“Bean 定义”阶段做了哪些工作。
容器刷新前的准备 提前总结: SpringApplication 先创建容器对象 context = AnnotationConfigServletWebServerApplicationContext,赋值其中成员 beanFactory = DefaultListableBeanFactory。容器对象创建完成后,成员 beanFactory 内已经有少数几个 BeanDefinidition 信息了,其中包括 ConfigurationClassPostProcessor。然后 SpringApplication 向容器对象成员 beanFactory 中注册了启动类 DemoApplication 的 BeanDefinidition。
在 SpringAppliction.run(String… args) 方法中,创建 IoC 容器 AnnotationConfigServletWebServerApplicationContext 时,反射调用该类及其父类们的无参构造方法,初始化成员 beanFactory = DefaultListableBeanFactory。
在容器 AnnotationConfigServletWebServerApplicationContext 自己的无参构造中,初始化成员 reader = AnnotatedBeanDefinitionReader 。在 AnnotatedBeanDefinitionReader 的构造函数中,调用了AnnotationConfigUtils.registerAnnotationConfigProcessors() 方法,这个方法内往容器成员 beanFactory 中注册了几个指定的 Bean 定义(RootBeanDefinition 类型),其中包括 ConfigurationClassPostProcessor ,下面会介绍它。
从 AnnotatedBeanDefinitionReader 源码可以看出,它的作用是手动注册某个 Bean 的定义信息。这个在容器开始扫描所有 Bean 之前很好用,这是因为有一些 Bean 需要在扫描前就被初始化,例如启动类的 Bean。
回到 SpringAppliction.run(String… args) 方法,创建好容器后,调用本类的prepareContext方法,这个方法内最后调用SpringApplication.load()方法。
SpringApplication.load() 部分源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 protected void load (ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this .beanNameGenerator != null ) { loader.setBeanNameGenerator(this .beanNameGenerator); } if (this .resourceLoader != null ) { loader.setResourceLoader(this .resourceLoader); } if (this .environment != null ) { loader.setEnvironment(this .environment); } loader.load(); }
参数1context为已创建的容器对象,参数2sources只有一个元素,就是启动类 Class 对象,如”DemoApplication.class”(来源是 SpringApplication.run() 方法时的第一个参数)。在这个方法内,创建 BeanDefinitionLoader 对象,再通过 BeanDefinitionLoader 对象内成员AnnotatedBeanDefinitionReader(与容器内的 reader 不是同一个对象,但它的成员 registry 与 容器内的 beanFactory 是同一个对象),向容器中注册了启动类 DemoApplication 的 Bean 定义(AnnotatedGenericBeanDefinition 类型)。主要负责这个注册工作的是AnnotatedBeanDefinitionReader.doRegisterBean()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 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); if (this .conditionEvaluator.shouldSkip(abd.getMetadata())) { return ; } abd.setInstanceSupplier(supplier); ScopeMetadata scopeMetadata = this .scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this .beanNameGenerator.generateBeanName(abd, this .registry)); AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); 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)); } } } if (customizers != null ) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this .registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this .registry); }
上面源码取 beanName 时,用的是AnnotationBeanNameGenerator.generateBeanName(),当 Bean 定义对象是 AnnotatedBeanDefinition 的子类时(AnnotatedGenericBeanDefinition 就是),用的是下面这个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 protected String determineBeanNameFromAnnotation (AnnotatedBeanDefinition annotatedDef) { AnnotationMetadata amd = annotatedDef.getMetadata(); Set<String> types = amd.getAnnotationTypes(); String beanName = null ; for (String type : types) { AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); if (attributes != null ) { Set<String> metaTypes = this .metaAnnotationTypesCache.computeIfAbsent(type, key -> { Set<String> result = amd.getMetaAnnotationTypes(key); return (result.isEmpty() ? Collections.emptySet() : result); }); if (isStereotypeWithNameValue(type, metaTypes, attributes)) { Object value = attributes.get("value" ); if (value instanceof String) { String strVal = (String) value; if (StringUtils.hasLength(strVal)) { if (beanName != null && !strVal.equals(beanName)) { throw new IllegalStateException("Stereotype annotations suggest inconsistent " + "component names: '" + beanName + "' versus '" + strVal + "'" ); } beanName = strVal; } } } } } return beanName; }
注释中所说的“复合注解”举例:@SpringBootApplication 下包含 @EnableAutoConfiguration,@EnableAutoConfiguration 下又包含 @Import 等。
这个方法的含义是,从当前 bean 的所有注解中找 @Component 注解,如果有 @Component 注解且指定了 value 属性,则 beanName=value属性值,否则 beanName=null。当这个方法返回的 beanName=null 时,就会用另一个方法:取类名,第一个字母小写。
例如我们的启动类一般不会特意用 @Component 指定 bean 名字(@SpringBootApplication 指定不了),所以启动类的 beanName 就是取类名,第一个字母小写。
问题:注册 Bean 定义时,为什么加了 @Conditional注解就不继续?@Conditional只是控制一个bean在特定条件下才注入。 ???
容器刷新 在 AbstractApplicationContext.refresh() 方法中,调用本类中的 invokeBeanFactoryPostProcessors 方法,参数是 beanFactory = DefaultListableBeanFactory。在这个方法中,又调用了PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法。
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() 方法参数1是 beanFactory,参数2是容器中已添加的 BeanFactoryPostProcessor(是在上一节“容器刷新前的准备”阶段添加的, 这里不用关注有哪些)。这个方法的作用是取出容器中当前已保存的、实现了 BeanFactoryPostProcessor 接口的 Bean,并初始化这些 Bean,然后调用这些 Bean 的,以及“参数2”中的 Bean 的 postProcessBeanFactory 方法,若 Bean 实现的接口是 BeanDefinitionRegistryPostProcessor(该接口继承了 BeanFactoryPostProcessor),会先调用其 postProcessBeanDefinitionRegistry 方法,再调用其 postProcessBeanFactory 方法。
【PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() 方法的详细解读见附录1。
在上一节说过,容器刚创建时就注册了 ConfigurationClassPostProcessor 的 BeanDefinidition 对象,它就是 BeanDefinitionRegistryPostProcessor 接口的实现类,所以在这个方法内会创建并实例化它的 Bean,再调用它的 postProcessBeanDefinitionRegistry 方法。
ConfigurationClassPostProcessor 是在“Bean 定义”阶段最关键的一个类,XXXXXXXXXXXXXXX
这个类做了什么?
1、 取出容器当前拥有的 BeanDefinidition 对象,判断它们是否是配置类,不是配置类的不处理,是配置类的继续处理。
这里判断是不是配置类的方法是ConfigurationClassUtils.checkConfigurationClassCandidate。简单地说,类上有这些注解之一的:@Configuration、@Component、@ComponentScan、@Import、@ImportResource,或类中方法有注解 @Bean 的,都算配置类。
PS: 从实际使用经验上来说,类上不标任何注解,只在方法上标注解 @Bean,是不起作用的,原因是这样的类在扫描时就扫不到,更进不到这个判断方法。
在这一步,本身容器中已注册的 BeanDefinidition 就不多,再经过筛选,就只剩下启动类如”DemoApplication”的 BeanDefinidition 会被继续处理了。
@Import 注解可用于导入一个或多个 Bean,它和 @Bean 的区别就是它是标在类上。@ImportResource 类似,但它是用于导入配置文件。
2、 如果筛选完有多个配置类的话,若配置类上有标@Order注解,会排个序,按注解value值升序排序,所以值越小的优先级越高。
3、 创建ConfigurationClassParser,调用这个类的 parse 方法处理筛选出的配置类 BeanDefinidition 对象(只有启动类一个),这个类最后调用到doProcessConfigurationClass方法。
1 2 3 4 protected final SourceClass doProcessConfigurationClass ( ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {...}
通过方法内注释可以知道,这个方法会处理被这些注解标注的配置类:@PropertySource(可以和@Value注解配合使用读取配置项)、@ComponentScan、@Import、@ImportResource,和用 @Bean 标注的方法。
已知,Spring 会根据启动类上的 @ComponentScan 注解,扫描启动类所在包下所有的 Bean 定义信息,保存到 beanFactory=DefaultListableBeanFactory 中。这里就来说说 ConfigurationClassParser 是怎么处理 @ComponentScan 注解的。
附录1:PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 public static void invokeBeanFactoryPostProcessors ( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class , true , false ) ; for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class )) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class )) ; processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class , true , false ) ; for (String ppName : postProcessorNames) { 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); currentRegistryProcessors.clear(); boolean reiterate = true ; while (reiterate) { reiterate = false ; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class , true , false ) ; for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class )) ; processedBeans.add(ppName); reiterate = true ; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class , true , false ) ; List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { } 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); } } sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class )) ; } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class )) ; } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); beanFactory.clearMetadataCache(); }
总结这个方法做的事:
执行 BeanDefinitionRegistryPostProcessor 类型的、实现了 PriorityOrdered 接口的 postProcessor 的 postProcessBeanDefinitionRegistry 方法 — 这里会执行到 ConfigurationClassPostProcessor
执行 BeanDefinitionRegistryPostProcessor 类型的、实现了 Ordered 接口的 postProcessor 的 postProcessBeanDefinitionRegistry 方法
执行 BeanDefinitionRegistryPostProcessor 类型的、没有实现 PriorityOrdered/Ordered 接口的 postProcessor 的 postProcessBeanDefinitionRegistry 方法
执行方法参数中实现了 BeanDefinitionRegistryPostProcessor 的,和前面三步的BeanDefinitionRegistryPostProcessor 类型的 postProcessor 的 postProcessBeanFactory 方法
执行方法参数中未实现 BeanDefinitionRegistryPostProcessor 的 postProcessor 的 postProcessBeanFactory 方法
执行 BeanFactoryPostProcessor 类型的、实现了 PriorityOrdered 接口的 postProcessor 的 postProcessBeanFactory 方法
执行 BeanFactoryPostProcessor 类型的、实现了 Ordered 接口的 postProcessor 的 postProcessBeanFactory 方法
执行 BeanFactoryPostProcessor 类型的 postProcessor 的 postProcessBeanFactory 方法