代码:
public void testWithSpring() throws Exception {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MovieConfig.class);
MovieLister lister = (MovieLister) ctx.getBean(“movieLister”);
}
关键对象
====
为了更好的方便理解,我们尝试着将现实世界的对象一一映射到虚拟世界
现实世界
====
这里我们以饭店举例
几个关键的对象:
海鲜加工饭店
有自己的招牌和特色,不过注意该饭店所有食材均需要客户自带。
出单系统
客户点菜下单(到前台或者找服务员都行,因为自己带的菜还要交给饭店嘛)后自动将客户的订单打印出来,打印出来的订单除了菜名还会加上:序号、桌位号、菜品的口味等。职责就是简洁清晰的打印出订单信息,供厨师或其他人使用。
订单复核员
我们这个餐厅必须要做一个步骤,就是订单出单后再去找客户确认订单,订单确认了才能交给厨房去做,这样做的目的一来是为了避免客户误点或沟通失误,二来通过确认的沟通也提升了用户体验。
为什么我们这里这个角色叫订单复核员,而不叫服务员呢,因为我们的印象里服务员能干很多其他的事情,这样的话反而弱化了订单确认的这个关键动作。
后厨
根据送过来的食材和订单做菜,后厨关注的是如何根据订单和食材来把菜做好。
虚拟世界
====
直接看这个图可能会有一点懵,我们后面再详细一一进行说明和讲解,请注意,我们本章节后文都是围绕该图进行讲解,此图非常重要。
现实世界 | 虚拟世界 | 说明 |
海鲜加工饭店 | ApplicationContext | 对标海鲜加工饭店,厨房里的厨子都是他的打工仔,他制定出精美的菜单来吸引食客,@Component、@Configuration、@Bean都是它的金字招牌菜,其实就是对厨子进行了包装,且有门面吸引客源。 |
海鲜菜单 | Java config | Spring IoC独有的招牌菜:@Component @ComponentScan @Bean @Import等美味 |
后厨 | BeanFactory | 根据食材和订单做菜;没有饭店实体店则基本只能做点路边摊小买卖。 |
出单系统 | BeanDefinitionRegistryPostProcessor | 相当于出单系统,把客户想要的菜给转化到订单上,例如 也是BeanFactoryPostProcessor的子类 |
订单复核员 | BeanFactoryPostProcessor | 确认订单信息时菜还没做,例如可以允许客户对订单做一些信息修改 |
订单 | BeanDefinition | 即订单信息,后厨要看着订单来做菜 |
成品 | Bean | 最终的产物 |
从上面的例子我们大致能够区分出了BeanFactory和ApplicationContext的区别。
Spring可以让我们参与到任意一个角色中:客户、海鲜加工饭店老板、出单系统、订单复核员、后厨,可以参与到其中任意环节中。
那我们可以做些什么有趣事情呢?
例如可以制定我们特色的菜单,像mybatis的@Mapper特色菜。
确认订单时给所有订单信息里加赠饮料(xml声明的bean的属性里${xx}占位符的替换)等
初步理解了这些关键对象之后,我们再深入到各个环节,看看各个环节都是怎么干的
BeanFactory
===========
给我提供订单信息和原材料我就做,订单和食材缺一不可
让我们先聚焦后厨,因为后厨是饭店的核心。
在spring framework中,Bean的生命周期在Beanfactory里就已经闭环了
ApplicationContext只是加一些料,例如扫描java config转义成BeanDefinition给到BeanFactory,然后再添加一些BeanPostProcessor等。
注意本文重点关注的是基于主流java config配置的实现,其实xml文件的配置原理也类似,不是本文重点不做探讨。
BeanFactory的生命周期是什么,其实就是用
BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor 这两个接口的实现类,往BeanFactory注册BeanDefinition和修改BeanFactory里的BeanDefinition及其他信息。
BeanDefinition
==============
订单信息在虚拟世界长什么样的?它起到了承上启下非常关键的作用。
为什么一开始要先讲BeanDefinition呢,不管基于什么配置方式都需要生成BeanDefinition,在Bean的生命周期中,第一步也是getMergedBeanDefinition。
我们先来看一下BeanDefinition的类图继承关系
BeanDefinition实现类与各个场景的对应,这里我们只关注java config场景的
配置场景 | BeanDefinition实现类 | 说明 |
@Component及其子类, 例如: @Configuration @Service | AnnotatedGenericBeanDefinition | 无 |
@Bean | ConfigurationClassBeanDefinition | 无 |
@ComponentScan扫描到的类: | ScannedGenericBeanDefinition | 无 |
无 | RootBeanDefinition | 将parentName的bean进行合并整合的结果 |
常用于xml配置文件声明的bean | GenericBeanDefinition | 无 |
RootBeanDefinition(merged bean definition)
==========================================
Bean生命周期中最重要的BeanDefinition实现类
因为不管中间过程中是什么BeanDefinition,不管玩出什么花样
最终在bean生命周期中都会变成 RootBeanDefinition
当整合成RootBeanDefinition 后,故而spring 会给我们留了一个统一的后置处理器:
MergedBeanDefinitionPostProcessor
BeanDefinition的属性:
属性 | 类型 | 说明 |
parentName ChildBeanDefinition | String | 相当于java的继承父类,spring最后会把所有类型的bean都重新揉到一起形成一个新的RootBeanDefinition; 只有ChildBeanDefinition才有该属性值 |
beanClass AbstractBeanDefinition | Object | 可以为string 也可以为 class<?> 也可以为空,为空时基本都是要通过factoryBeanName、factoryMethodName去实例化对象 |
scope | String | 值: singleton prototype refresh (spring cloud) 默认为空,为空时就当单例处理] singleton 详见@Scope注解; @Scope注解的使用还是有点窍门的,例如@RefreshScope是什么原理? |
lzyInit | Boolean | 是否延迟加载
详见@Lazy |
autowireMode AbstractBeanDefinition | int | 这里其实就是DI的几种注入方式了,目前java config已经很灵活,直接注解的形式去定义就行了 AUTOWIRE_NO(默认值) 默认装配模式, 目前非xml配置都是使用这种方式,然后程序员使用注解手动注入 AUTOWIRE_BY_NAME 通过set方法,并且 set方法的名称需要和bean的name一致 AUTOWIRE_BY_TYPE 通过set方法,并且再根据bean的类型,注入属性,是通过类型配置 AUTOWIRE_CONSTRUCTOR 通过构造函数注入 Spring @Bean注解的autowire属性可以给我们去设置该属性,也能通过BeanFactoryPostProcessor去修改BeanDefinition的autowireMode;不过一般也用不到去修改这个。 @Bean因为是注解在方法上,所以是AUTOWIRE_CONSTRUCTOR @Autowired 是在AutowiredAnnotationBeanPostProcessor里默认通过类型判断去找对应的bean,类似于AUTOWIRE_BY_TYPE,也是在这里处理@Qualifier注解的bean name查找。因为@Autowired只是一个属性值不是BeanDefinition,所有没有autowireMode属性一说 |
dependsOn | String[] | 依赖了哪些bean,加载该bean时会先去加载依赖的bean,再来加载该bean 详见@DependsOn() |
autowireCandidate | Boolean | 设置当前bean在被其他对象作为自动注入对象的时候,是否作为候选bean,默认true 如果设为false则别的bean引用不到该bean @Scoped(“”)值不为空时,bean原始的BeanDefinition会被设置为autowireCandidate =false,会新生成一个新的beanClass为代理类class的BeanDefinition设置autowireCandidate=true,即替换了掉原来的beanDefinition |
primary | Boolean | 设置是不是最优先的候选bean 只对使用者产生影响,对原始对象的构造不起任何影响,原始对象该生成bean还是生成;只是后面被其他地方用于时,BeanFactory去判断选择 @Primary |
qualifiers AbstractBeanDefinition | Map<String, AutowireCandidateQualifier> | Register a qualifier to be used for autowire candidate resolution, keyed by the qualifier's type name 只对使用者产生影响,对原始对象的构造不起任何影响,原始对象该生成bean还是生成;只是后面被其他地方用于时,BeanFactory去判断选择 @Qualifier 需和@Autowired一起使用 |
instanceSupplier AbstractBeanDefinition | Supplier<?> | 实例化对象的提供者,基本用不上自定义 |
isFactoryBean RootBeanDefinition | Boolean | 是否实现了FactoryBean接口,只要没实现FactoryBean接口的都是false; |
factoryBeanName | String | 与isFactoryBean无关 可以是任意的beanName,且不需要实现FactoryBean接口 |
factoryMethodName | String | 与isFactoryBean无关 通过该方法取bean,需要结合factoryBeanName进行使用 |
constructorArgumentValues | ConstructorArgumentValues | 构造函数的定义,包含参数顺序等 |
propertyValues | MutablePropertyValues | 常用于xml声明的bean;将xml该bean的所有property标签键值对放这里; 也可以用于spring内部上下文传递一些bean的信息,就像Servlet HttpRequest.setAttribute(key,value) |
initMethodName | String | 初始化方法名 |
destroyMethodName | String | Bean销毁时触发的方法名 |
role | int | 是由什么系统声明的bean ROLE_APPLICATION ROLE_SUPPORT ROLE_INFRASTRUCTURE |
description | String | Bean的描述,常用于xml配置里的<description>节点 |
isSingleton | boolean | 判断scope.equals(“singleton”) |
IsPrototype | boolean | 判断scope.equals(“prototype”) |
isAbstract | String | 是否抽象类 |
FactoryBean接口相关
两种方式:
实现了spring FactoryBean接口的BeanDefinition属性isFactoryBean=true(RootBeanDefinition,merge beandefinition后可见)
例如@Configuration注解生成的bean,mybatis的mapper都是用到了FactoryBean接口的内容
注意factoryBeanName、factoryMethodName 的使用是另一种实现方式,此时isFactoryBean=false
BeanDefinitionRegistryPostProcessor
===================================
根据菜单和客户下单时的信息,生成订单给后厨
作用于BeanFactory,是BeanFactory给外界留的门,具体的执行是在ApplicationContext的生命周期里。
在spring里就是将@Configuration、@Bean等配置信息解析生成BeanDefinition注册到BeanFactory。
其继承自BeanFactoryPostProcessor
出单系统必须实现
BeanDefinitionRegistryPostProcessor接口方法
(ApplicationContext饭店自己也可以给后厨下单 例如
ClassPathXmlApplicationContext,就可以在applicationContext生命周期里(refresh方法内,下单给后厨之前)解析xml往Beanfactory里注册BeanDefinition)
因为也继承了BeanFactoryPostProcessor接口,所以一般也自带了确认订单的功能
例如一些典型的实现:
1、java config的关键实现类:
ConfigurationClassPostProcessor
2、mybatis的 MapperScannerConfigurer,将@Mapper接口注册成BeanDefinition
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor
注:MapperScannerConfigurer只是Mybatis mapper注入的其中一种方式
ConfigurationClassPostProcessor
===============================
**最重要的
BeanDefinitionRegistryPostProcessor实现类没有之一**
我们用的java config都是经它之手转变为BeanDefinition,因为
BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,所以也实现了postProcessBeanFactory方法。本文的重点在于IoC的过程理解,所以本章节主要还是描述该Processor源码的实现过程。
ConfigurationClassPostProcessor其postProcessBeanFactoryRegistry方法负责注册bean,将@Configuration @ComponentScan等注解解析成BeanDefinition注册到BeanFactory;postProcessBeanFactory方法负责修改BeanDefinition,将@Configuration注解的类的BeanDefinition的beanClass替换为代理后的class name。
该
BeanDefinitionRegistryPostProcessor也不是从石头里蹦出来的,后面ApplicationContext的生命周期会讲到是何时触发的。
postProcessBeanFactoryRegistry
==============================
循环当前所有的BeanDefinition,找那些有@Configuration注解的类进行处理,也可以有内部类,一样会去加载,不过排序是跟着外层的@Configuration一起走,@Configuration也可以加@Order注解用于将所有@Configuration的bean进行排序后按从小到大的顺序加载
也可以结合@Conditional注解使用,如果不满足Conditional条件,则不加载该Configuration
一、找到当前BeanFactory里所有@Configuration注解的BeanDefinition并通过@Order进行排序
二、循环找到的BeanDefinition,将其转化为ConfigurationClass
2.1先处理如果class有嵌套类,如果有@Configuration 或@Component 注解,同样转化为独立的ConfigurationClass
2.2 @PropertySources @PropertySource的处理,添加PropertySource至environment
2.3 @ComponentScans @ComponentScan的处理,扫描java config注解。将扫描到的class转换为BeanDefinition;然后再调用上面第一步,类似于递归调用
2.4 @Import的处理
注解value值是ImportSelector接口实现类的,直接调用接口方法selectImports拿到返回String[],class类名集合,再次去调用processImports方法
注解value值是
ImportBeanDefinitionRegistrar接口实现类的,添加至ConfigutaionClass的属性importBeanDefinitionRegistrars【关键】
注解value不是上面两种接口实现类的,直接再走判断注解转化ConfiurationClass的处理
2.5 @ImportResource的处理,添加至ConfigutaionClass的属性ImportedResource
2.6找到**@Bean**注解的method,添加至ConfigurationClass的属性beanMethod
2.7找当前class的接口,如果有@Bean注解的method,添加至ConfigurationClass的属性beanMethod(因为java8的interface有default method的存在,所以接口方法也可以生成bean)
2.8找当前class的父类,如果有@Configuration 或@Component 注解,同样转化为独立的ConfigurationClass(同嵌套类的处理)
三、将所有ConfigurationClass转换为BeanDefinition注册到BeanFactory
四、将所有ConfigurationClass的beanMethod转换为BeanDefinition注册到BeanFactory.
五、将所有ConfigurationClass的ImportedResource转换为BeanDefinition注册到BeanFactory.
六、将所有ConfigurationClass的
importBeanDefinitionRegistrars,调用其registerBeanDefinitions方法进行BeanDefinition的注册,同BeanDefinitionRegistryPostProcessor,也是用于注册BeanDefinition【关键】
另外@Conditional可以结合@Configuration、@Bean注解进行使用,不满足条件的不加载为BeanDefinition
@Configuration
@Component
public @interface Configuration {
ConfigurationClass对象关键属性(解析@Configuration、@Component注解的类后得到的结果)
属性 | 类型 | 说明 |
metadata | AnnotationMetadata | @Configuration 类的注解集合 |
beanName | String | Pojo类名 |
beanMethods | Set<BeanMethod> | @Bean 的方法集合 |
importedResources | Map<String, Class<? extends BeanDefinitionReader>> | 待加载的xml配置文件 |
importBeanDefinitionRegistrars | Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> | 待加载的
用于注册BeanDefinition |
@Bean
=====
这里@Configuration或者@Component注解里的@Bean注解的方法,会注册为BeanDefinition,然后其BeanClass为空,factoryBeanName为其@Configuration或者@Component类的beanName;factoryMethodName就是 @Bean注解的方法名。
这里就是用到了BeanDefinition内容里的factoryBeanName和factoryMethodName进行处理,委托其他类(@Configuration类)来生成bean。
@Import
=======
对后面理解spring boot AutoConfiguration至关重要
一、注解value值是ImportSelector接口实现类的,直接调用接口方法selectImports拿到返回String[],class类名集合,再次去进行扫描
**二、注解value值是
ImportBeanDefinitionRegistrar接口实现类的,会调用其registerBeanDefinitions方法,进行BeanDefinition注册;**
等于实现了
BeanDefinitionRegistryPostProcessor的功能。
三、注解value值不是上面两种接口实现类的,直接扫描该类
Spring boot starter自动引入的核心
@EnableAutoConfiguration
public @interface SpringBootApplication {
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
public class AutoConfigurationImportSelector implements ImportSelector {
该selector会去扫描所有spring.factories文件里
org.springframework.boot.autoconfigure…EnableAutoConfiguration 属性的类
Mybatis @MapperScan
@Import(MapperScannerRegistrar.class)
Feign @EnableFeignClients
@Import(FeignClientsRegistrar.class)
这里一般都是注册的GenericBeanDefinition
postProcessBeanFactory
======================
这里涉及到AOP的知识
处理java-config相关的注解 @Configuration @ComponentScan @Import等将他们转换成BeanDefinition并注册到BeanFactory中,具体的实现也涉及到AOP知识。因为我们关注的是整体的运作流程。
将@Configuration注解转换的BeanDefinition,BeanClass属性改成 AOP代理后生成的class,这样后面bean生命周期实例化的就是代理后的class
为什么要用代理?
@Configuration
public class MovieConfiguration {
@Bean
public MovieLister movieListener(){
return new MovieLister (this.movieFinder ());
}
@Bean
public MovieFinder movieFinder(){
return new ColonDelimitedMovieFinder (“movies1.txt”);
}
}
而且此处通过AOP增强后,也不会面临内部方法调用AOP失效的问题(为什么?movieListener这里面调用movieFinder不是已经在super class了吗,其实并不是,这个父类其实也是被代理的,cglib的实践,因为只要是@Bean注解的方法都被代理拦截了,如果方法名没被代理的话,那就真是直接执行super的原始代码),如上最后movieListener里的movieFinder属性,和下面movieFinder方法生成的bean,是同一个bean;感兴趣的可以去看看源码
如何查看cglib增强后的代码,可以再main函数第一行加上如下设置即可
public static void main(String[] args) {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,“C://”);
@Component注解(包括其子类@Service @Controller)的类也可以声明 @Bean,区别是什么呢,就是是LITE 轻量模式,不会像上面这样生成代理(@Configuration是FULL模式),即上面的 movieListenner里的movieFinder对象和 BeanFactory里的bean movieFinder 是两个不同的对象。
BeanFactoryPostProcessor
========================
有个客户突然跑过来后厨说 我刚刚下单忘了说清蒸鲈鱼不要鱼
接单后可以对订单做的事情,主要是对订单的修改,取消基本上不可能的,就像你到饭店吃饭,中途想问问服务员有个菜没做的话能不能帮我退掉,这时候服务员肯定给你讲正在做了不能退了。
作用于BeanFactory,是BeanFactory给外界留的门,具体的执行是在ApplicationContext的生命周期里。
经典实用场景,BeanDefinition属性值变量的替换
对BeanDefinition属性值进行修改,不管哪里注册的,都会走这里
经典常用的:
PropertySourcesPlaceholderConfigurer
BeanDefinition里面如下属性值变量的替换都在这里执行(@Autowired和@Value里的变量并不在这进行替换 、SpEL也不在此处处理)
替换BeanDefinition属性值的范围和顺序如下:
parentName
beanClassName
factoryBeanName
factoryMethodName
scope
propertyValues
constructorArgumentValues
Bean的生命周期
=========
实在是编不下去了,这个用做菜来举例的话,我头发要白一大片。这里我们就不以做菜举例了,只能以类的创建来举例了
正常创建类的流程:
(1)MovieListener listener = new MovieListener();
MovieFinder finder = new ColonDelimitedMovieFinder(“movies1.txt”);
(2)listener.setFinder(finder);
listener.setStartTime(new Date());
(3)listener.init();
对应上面三个步骤,我们分为三个方法:
1、实例化
2、populateBean属性赋值(@Autowired的属性依赖注入都是在这里处理)
3、初始化(属性赋值完后,我们做好准备工作对外开始服务)
所以spring为了让我们参与到bean的实例化与初始化过程,特意给我们留了口
为什么要划分出多一个第二步populateBean方法呢,拆分的更细其实也是有益处的,例如spring cloud的结合@RefreshScope和@ConfigurationProperties使用的bean,就用到了bean生命周期中的destroy和initializeBean 初始化的方法,跳过了实例化和属性赋值,直接去触发
ConfigurationPropertiesBindingPostProcessor进行@ConfigurationProperties注解类的属性值的绑定(这里的属性赋值并不是@Autowired @Value这样的属性赋值,而是@ConfigurationProperties(prefix = “xxx”)注解类对应的属性);因为是再次第三步初始化的initializeBean,所以第二步依赖注入的属性不会被改变,节省了成本
BeanPostProcessor
=================
在bean的生命周期中,我们能参与到哪些环节呢,spring给我们的最主要的还是通过三类BeanPostProcessor去参与进去。
BeanPostProcessor的类的继承关系
典型常用的BeanPostProcessor如下:
CommonAnnotationBeanPostProcessor
spring中最重要的BeanPostProcessor之一
@Resource
注解属性的赋值,找到对应的bean进行属性赋值
@WebServiceRef
不常用,不解释
继承自
InitDestroyAnnotationBeanPostProcessor又包含如下两个注解的处理
@PostConstruct
执行该注解对应的方法,在何时执行请看“虚拟世界”的图例
@PreDestroy
销毁时执行改注解方法,我们要搞清楚如何出生的,再去想如何没的,这里不做解释。
AutowiredAnnotationBeanPostProcessor
Spring boot中最重要的BeanPostProcessor 没有之一
@Autowired
常见问题:
为什么spring bean 一级缓存里没有 ResourceLoader、ApplicationContext、ApplicationEventPublisher、BeanFactory相关的bean,@Autowired为什么能注入对象进去呢?
也是这里进行了代码相关的类型判断,如果是上面4种类型的,直接找到对应的对象赋值了。
@Value
${xx} #{xx} 占位符的区别是什么 就是普通属性替换和SpEL的执行
@Qualifier
需配合@Autowired使用,@Autowired在找相关的bean时,也会按@Qualifier指定的bean name去查找。
ConfigurationPropertiesBindingPostProcessor
Spring boot中重要的BeanPostProcessor
@ConfigurationProperties注解类的处理
AnnotationAwareAspectJAutoProxyCreator
AOP里用到,Spring AOP 最重要的BeanPostProcessor没有之一
@Aspect的处理,将aop扫描到的方法类进行生成aop代理,这里我们也不做过多的解释,属于AOP的内容。
下面的章节我们将正式进入bean的生命周期,这里再回顾一下我们的虚拟世界
getMergeBeanDefinition
======================
合并BeanDefinition
为什么要合并BeanDefinition,我们这里用词还是跟spring源码里的方法名保持了一致,是为了方便大家看源码时能更好去对应上。
因为java面向对象设计的概念,类是可以继承的
如下这种xml声明方式,parent就有用,生成bean时会将parent bean的属性也进行注入,这样就能使用到父类的属性和方法。
Java config基于@Component注解时基本用不上了,因为生成的都不是ChildBeanDefinition
怎么合并,去看一下AbstractBeanDefinition的构造函数就知道各种其他类型的BeanDefinition如何转换为RootBeanDefinition,我们这里就不贴源码了。
Instantiation 实例化
=================
什么叫实例化 new MovieListener() 这样吗
涉及到static 方法块是否需要被执行,以及构造函数是否需要被执行,spring默认都是会执行到
postProcessBeforeInstantiation
==============================
由
InstantiationAwareBeanPostProcessor触发
这里可以干些什么,有什么使用场景,如果在这里有返回对象,则会直接跳到
BeanPostProcessor.postProcessAfterInitialization方法去,等于是直接跳到生命周期的末尾,期间的生命周期都不会执行
createBeanInstance
==================
这里呢,有什么场景暂时没发现,不过spring也给我们参与的机会=>BeanDefinition里的instanceSuplier
postProcessMergedBeanDefinition
===============================
由
MergedBeanDefinitionPostProcessor触发
这里可以干些什么,有什么使用场景,spring为什么要给我们留这个口?
在
BeanDefinitionRegistryPostProcessor注册BeanDefinition可以是任意类型,但是在bean的生命周期里(实例化之前),都会转变为RootBeanDefinition;所以这里spring给我们留了一个口,让我们还去访问RootBeanDefinition,可以用于获取信息和修改BeanDefinition信息;
首先搞清楚什么是:merged bean definition
Return a RootBeanDefinition for the given bean, by merging with the
parent if the given bean’s definition is a child bean definition.
在BeanDefinition生成的时候就已经merge过了,不管如何,实例化之前会拿到mergedBeanDefinition(实际是RootBeanDefinition类型)
**既然可以用于修改BeanDefinition,为什么该后置处理不在对象实例化之前给我们去调用呢?**如果是修改BeanDefinition,那么其实是跟BeanFactoryPostProcessor去修改BeanDefinition是有歧义的。如果想要修改Bean的实例化的类,还是得去BeanFactoryPostProcessor,这里只能影响实例化之后的生命周期。
这里其实就是给最后一次机会,能够去修改BeanDefinition(注意这里bean已经实例化了)
AutowiredAnnotationBeanPostProcessor 和
CommonAnnotationBeanPostProcessor
在这里
postProcessMergedBeanDefinition 就是去提前缓存了每个类的 @Autowired、@Value等注解属性信息,后面postProcessProperties直接使用而已。 不到这里加缓存后面再去取也可以
到这里我们主要分析了
applyMergedBeanDefinitionPostProcessors这段代码的作用,它的执行时机是在创建对象之后,属性注入之前。按照官方的定义来说,到这里我们仍然可以使用这个方法来修改bd的定义,那么相对于通过BeanFactoryPostProcessor的方式修改bd,applyMergedBeanDefinitionPostProcessors这个方法影响的范围更小,BeanFactoryPostProcessor影响的是整个Bean的生命周期,而applyMergedBeanDefinitionPostProcessors只会影响属性注入之后的生命周期。
polulateBean 属性赋值
=================
为什么属性赋值要单独拿出来,其实是属于初始化里面的吗;在spring里还真不是,不过要注意的是spring cloud的@RefreshScope是直接调用了destroy方法之后直接调用初始化方法,跳过了属性赋值,其实也就是跳过了@Autowired @Value等的属性赋值处理保留原有的。
postProcessProperties
=====================
由
InstantiationAwareBeanPostProcessor触发
给bean的属性赋值
AutowiredAnnotationBeanPostProcessor 和
CommonAnnotationBeanPostProcessor
就是在此处分别给@Autowired @Value、@Resource属性通过反射赋值
postProcessPropertiesValues(Deprecated)
=======================================
由
InstantiationAwareBeanPostProcessor触发
目前已经作废,被上面postProcessProperties方法替代
applyPropertyValues
===================
BeanDefinition里propertyValues的SpEL的处理在这里,通过java config配置的类基本上已经用不到这里了
Initialization 初始化
==================
什么叫初始化,简单点说就是执行类的各种方法
各类Aware接口方法
===========
用于接收各类的spring对象
postProcessBeforeInitialization
===============================
由BeanPostProcessor触发
CommonAnnotationBeanPostProcessor
@PostConstruct注解的方法在此处调用执行