-
首先获取到所有的后置处理器 getBeanPostProcessors()
-
在 for 循环中依次调用后置处理器的方法
processor.postProcessBeforeInitialization(result, beanName); -
进入 postProcessBeforeInitialization 方法
org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization

进入 invokeAwareInterfaces(bean); 方法,当前 bean 实现了 ApplicationContextAware 接口。

ApplicationContextAwareProcessor#postProcessBeforeInitialization首先判断此 bean 是不是各种的Aware,如果是它列举的那几个 Aware 就获取 Bean 工厂的权限,可以向容器中导入相关的上下文环境,目的是为了 Bean 实例能够获取到相关的上下文,如果不是它列举的几个 Aware,那就调用invokeAwareInterfaces(bean),向容器中添加相关接口的上下文环境。
3.3 工厂后处理器方法(BeanFactoryProcessor 一系列接口)
包括 AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor 等。这些都是 Spring 框架中已经实现好的 BeanFactoryPostProcessor,用来实现某些特定的功能。
我们知道 Spring IoC 容器初始化的关键环节就在 org.springframework.context.support.AbstractApplicationContext#refresh 方法中 ,容器创建的主体流程都在这个方法里面,这个方法是真的重要!!!
对于工厂后处理器方法老周这里直接带你看 invokeBeanFactoryPostProcessors(beanFactory); 方法,这个方法处理的是 BeanFactoryPostProcessor 接口的 Bean。调用方法如下:

跟到最重要的方法里去,代码虽长,但逻辑中规中矩。
BeanFactoryPostProcessor:一切处理 BeanFactory 的父接口
BeanDefinitionRegistryPostProcessor:实现了 BeanFactoryPostProcessor 接口的接口

流程说明:
-
调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(registry) 方法。参数 beanFactoryPostProcessors 传入的优先处理掉。然后获取容器注册的,对于这些 Bean 按照 PriorityOrdered 接口、Ordered、没有排序接口的实例分别进行处理。
-
调用 BeanFactoryPostProcessor#postProcessBeanFactory(beanFactory) 方法。备注:BeanDefinitionRegistryPostProcessor 属于 BeanFactoryPostProcessor 子接口。先处理属于 BeanDefinitionRegistryPostProcessor 接口实例的 postProcessBeanFactory(beanFactory) 方法,然后获取容器注册的。对于这些 Bean 按照 PriorityOrdered 接口、Ordered、没有排序接口的实例分别进行处理。
3.4 Bean 级生命周期方法
可以理解为 Bean 类直接实现接口的方法,比如 BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean、DisposableBean 等方法,这些方法只对当前 Bean 生效。
3.4.1 Aware 类型的接口
Aware 类型的接口的作用就是让我们能够拿到 Spring 容器中的一些资源。基本都能够见名知意,Aware 之前的名字就是可以拿到什么资源,例如 BeanNameAware 可以拿到 BeanName,以此类推。调用时机需要注意:所有的 Aware 方法都是在初始化阶段之前调用的。
Aware 接口众多,这里同样通过分类的方式帮助大家记忆。Aware 接口具体可以分为两组,至于为什么这么分,详见下面的源码分析。如下排列顺序同样也是 Aware 接口的执行顺序,能够见名知意的接口不再解释。
Aware Group1
-
BeanNameAware -
BeanClassLoaderAware -
BeanFactoryAware
Aware Group2
-
EnvironmentAware -
EmbeddedValueResolverAware
这个知道的人可能不多,实现该接口能够获取 Spring EL 解析器,用户的自定义注解需要支持 SPEL 表达式的时候可以使用,非常方便。
ApplicationContextAware(ResourceLoaderAware/ApplicationEventPublisherAware/MessageSourceAware)
这几个接口可能让人有点懵,实际上这几个接口可以一起记,其返回值实质上都是当前的 ApplicationContext 对象,因为 ApplicationContext 是一个复合接口,如下:

Aware 调用时机源码分析

可以看到并不是所有的 Aware 接口都使用同样的方式调用。Bean××Aware 都是在代码中直接调用的,而 ApplicationContext 相关的 Aware 都是通过 BeanPostProcessor#postProcessBeforeInitialization() 实现的。感兴趣的可以自己看一下 ApplicationContextAwareProcessor 这个类的源码,就是判断当前创建的 Bean 是否实现了相关的 Aware 方法,如果实现了会调用回调方法将资源传递给 Bean。
BeanPostProcessor 的调用时机也能在这里体现,包围住 invokeInitMethods 方法,也就说明了在初始化阶段的前后执行。
关于 Aware 接口的执行顺序,其实只需要记住第一组在第二组执行之前就行了。
3.4.2 生命周期接口
至于剩下的两个生命周期接口就很简单了,实例化和属性赋值都是 Spring 帮助我们做的,能够自己实现的有初始化和销毁两个生命周期阶段。
InitializingBean对应生命周期的初始化阶段,在上面源码的invokeInitMethods(beanName, wrappedBean, mbd);方法中调用。
有一点需要注意,因为 Aware 方法都是执行在初始化方法之前,所以可以在初始化方法中放心大胆的使用 Aware 接口获取的资源,这也是我们自定义扩展 Spring 的常用方式。
除了实现 InitializingBean 接口之外还能通过注解或者 xml 配置的方式指定初始化方法,至于这几种定义方式的调用顺序其实没有必要记。因为这几个方法对应的都是同一个生命周期,只是实现方式不同,我们一般只采用其中一种方式。
DisposableBean类似于 InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了 DisposableBean 接口的 Bean 然后调用其 destroy() 方法,感兴趣的可以自行跟一下源码。
3.5 Spring Bean 生命周期流程图

4.1 BeanNameAware
该接口只有一个方法 setBeanName(String name),用来获取 bean 的 id 或者 name。
4.2 BeanFactoryAware
该接口只有一个方法 setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory。
4.3 ApplicationContextAware
该接口只有一个方法 setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext。
4.4 InitializingBean
该接口只有一个方法 afterPropertiesSet(),在属性注入完成后调用。
4.5 DisposableBean
该接口只有一个方法 destroy(),在容器销毁的时候调用,在用户指定的 destroy-method 之前调用。
4.6 BeanPostProcessor
该接口有两个方法:
-
postProcessBeforeInitialization(Object bean, String beanName):在初始化之前调用此方法 -
postProcessAfterInitialization(Object bean, String beanName):在初始化之后调用此方法
通过方法签名我们可以知道,我们可以通过 beanName 来筛选出我们需要进行个性化定制的 bean。
4.7 InstantiationAwareBeanPostProcessor
该类是 BeanPostProcessor 的子接口,常用的有如下三个方法:
-
postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用 -
postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、设置属性前调用 -
postProcessAfterInstantiation(Class beanClass, String beanName):在bean实例化之后调用
思路:创建一个类 UserBean ,让其实现几个特殊的接口,并分别在接口实现的构造器、接口方法中断点,观察线程调用栈,分析出 Bean 对象创建和管理关键点的触发时机。
5.1 UserBean 类
@Component
public class UserBean implements InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware {
private int id;
private String name;
public UserBean(int id, String name) {
this.id = id;
this.name = name;
System.out.println(“2. 调用构造函数”);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
System.out.println(“5. 属性注入 id”);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println(“5. 属性注入 name”);
}
@Override
public void setBeanName(String name) {
System.out.println(“6. 调用 BeanNameAware.setBeanName() 方法”);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
UserBean userBean = (UserBean) applicationContext.getBean(“userBean”);
System.out.println(userBean);
System.out.println(“7. 调用 BeanNameAware.setBeanName() 方法”);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(“9. 调用 InitializingBean.afterPropertiesSet() 方法”);
}
public void myInit() {
System.out.println(“10. 调用 init-method 方法”);
}
@Override
public void destroy() throws Exception {
System.out.println(“12. 调用 DisposableBean.destroy() 方法”);
}
public void myDestroy() {
System.out.println(“13. 调用 destroy-method 方法”);
}
@Override
public String toString() {
return “UserBean{” +
“id=” + id +
“, name='” + name + ‘’’ +
‘}’;
}
}
5.2 InstantiationAwareBeanPostProcessor 接口实现类
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (“userBean”.equals(beanName)) {
System.out.println(“1. 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法”);
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (“userBean”.equals(beanName)) {
UserBean userBean = (UserBean) bean;
System.out.println(“3. 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法”);
System.out.println(userBean);
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (“userBean”.equals(beanName)) {
System.out.println(“4. 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法”);
}
return null;
}
}
5.3 BeanPostProcessor 接口实现类
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。






既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)

总结
如果你选择了IT行业并坚定的走下去,这个方向肯定是没有一丝问题的,这是个高薪行业,但是高薪是凭自己的努力学习获取来的,这次我把P8大佬用过的一些学习笔记(pdf)都整理在本文中了
《Java中高级核心知识全面解析》

小米商场项目实战,别再担心面试没有实战项目:

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

战项目、讲解视频,并且后续会持续更新**
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-twR8RtZG-1712694073400)]
总结
如果你选择了IT行业并坚定的走下去,这个方向肯定是没有一丝问题的,这是个高薪行业,但是高薪是凭自己的努力学习获取来的,这次我把P8大佬用过的一些学习笔记(pdf)都整理在本文中了
《Java中高级核心知识全面解析》
[外链图片转存中…(img-YZuiXTKr-1712694073400)]
小米商场项目实战,别再担心面试没有实战项目:
[外链图片转存中…(img-fAhYcRHm-1712694073401)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-QzTkgzsI-1712694073401)]
965

被折叠的 条评论
为什么被折叠?



