Spring Bean的生命周期
Spring Bean的生命周期
Bean 的生命周期
整个生命周期如下所示
在创建 Bean 之前,Spring 容器会将所有 Bean 的信息(xml 里面的 <bean>
或者注解修饰的对象)封装成一个 BeanDefinition 对象,所有的 BeanDefinition 存储到一个名为 beanDefinitionMap 的 Map 集合中去,Spring 框架在对该 Map 进行遍历,然后创建对象,即如下过程
doCteateBean
该部分对应图中的初始化赋值部分
查看实现类 AbstractAutowireCapableBeanFactory 中的 doCteateBean 方法
继承类图
该方法是创建 bean 的开始,我们可以看到首先需要实例化这个 bean,也就是在堆中开辟一块内存空间给这个对象,createBeanInstance 方法里面逻辑大概就是采用反射生成实例对象,进行到这里表示对象还并未进行属性的填充,也就是 @Autowired 注解的属性还未得到注入
populateBean
该部分对应图中的依赖注入部分
initializeBean
该部分对应图中的 Aware 到 BeanPostProcessor#after 部分
我们可以看到第二步就是填充 bean 的成员属性,populateBean 方法里面的逻辑大致就是对使用到了注入属性的注解就会进行注入,如果在注入的过程发现注入的对象还没生成,则会跑去生产要注入的对象,第三步就是调用 initializeBean 方法初始化bean,
调用实现 Aware 接口的方法
可以看到 initializeBean 方法中,首先调用的是实现的 Aware 接口的方法,我们具体看一下 invokeAwareMethods 方法中会调用 Aware 接口的那些方法
我们可以知道如果我们实现了BeanNameAware,BeanClassLoaderAware,BeanFactoryAware三个Aware接口的话,会依次调用 setBeanName(), setBeanClassLoader(), setBeanFactory() 方法
对于 Await 接口的作用参考:
Aware 接口定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* A marker superinterface indicating that a bean is eligible to be notified by the
* Spring container of a particular framework object through a callback-style method.
* The actual method signature is determined by individual subinterfaces but should
* typically consist of just one void-returning method that accepts a single argument.
*
* <p>Note that merely implementing {@link Aware} provides no default functionality.
* Rather, processing must be done explicitly, for example in a
* {@link org.springframework.beans.factory.config.BeanPostProcessor}.
* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
* for an example of processing specific {@code *Aware} interface callbacks.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
*/
public interface Aware {
}Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的超级接口,实现了该接口的 bean 是具有被 Spring 容器通知的能力,通知的方式是采用回调的方式。
Aware 接口是一个空接口,实际的方法签名由各个子接口来确定,且该接口通常只会有一个接收单参数的 set 方法,该 set 方法的命名方式为 set + 去掉接口名中的 Aware 后缀,即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName),ApplicationContextAware(setApplicationContext)。
Aware 的子接口需要提供一个
setXxx
方法,我们知道 set 是设置属性值的方法,即 Aware 类接口的setXxx
方法其实就是设置 xxx 属性值的。 Aware 的含义是感知的、感应的,那么在 Spring 容器中是如何实现感知并设置属性值的呢?我们可以从初始化 bean 中的激活 Aware 的方法invokeAwareMethods()
中看到一点点,如下:从这,我们基本上就可以 Aware 真正的含义是什么了?感知,其实是 Spring 容器在初始化主动检测当前 bean 是否实现了 Aware 接口,如果实现了则回调其 set 方法,此时我们就能拿到对应的 XX 资源,对 XX 资源做一些处理;
补充:虽然这个名字叫 setXXX,但实际上更多的还是拿到这个资源。
Spring Aware 接口的实际应用场景是很多的,比如:
- 获取 Spring 容器的上下文信息:通过 ApplicationContextAware 接口可以获取 Spring 容器的上下文信息,可以在 Bean 中使用 Spring 容器提供的各种服务,如事件机制、AOP、事务管理等。
- 动态加载资源:通过 ResourceLoaderAware 接口可以获取 ResourceLoader,可以在 Bean 中动态加载资源,比如配置文件、模板文件等。
- 操作 Servlet 相关的信息:通过 ServletConfigAware 和 ServletContextAware 接口可以获取 Servlet 相关的信息,可以在 Bean 中操作 Servlet 相关的信息,比如获取 ServletContext 初始化参数、ServletContext 监听器等。
- 获取 Bean 工厂的信息:通过 BeanFactoryAware 接口可以获取 BeanFactory,可以在 Bean 中使用 BeanFactory 提供的各种服务,如 Bean 生命周期管理、依赖注入、AOP、事务管理等。
总之,Spring Aware 接口可以让 Bean 更好地与 Spring 容器进行交互,实现更灵活、更强大的功能。但需要注意的是,在实际使用中,应该避免滥用 Spring Aware 接口,因为过多地使用会导致 Bean 与 Spring 容器的紧耦合,降低代码的可维护性和可重用性。
调用 before… 方法
可以看到 applyBeanPostProcessorsBeforeInitialization 方法中,如果有类实现了 BeanPostProcessor 接口,就会执行postProcessBeforeInitialization 方法,这里需要注意的是:如果多个类实现 BeanPostProcessor 接口,那么多个实现类都会执行 postProcessBeforeInitialization 方法,可以看到是 for 循环依次执行的,还有一个注意的点就是如果加载 A 类到spring容器中,A 类也重写了 BeanPostProcessor 接口的postProcessBeforeInitialization 方法,这时要注意 A 类的 postProcessBeforeInitialization 方法并不会得到执行,因为A类还未加载完成,还未完全放到 Spring 的 singletonObjects 一级缓存中。
执行 init-method 方法
可以看到 invokeInitMethods 方法中,如果实现了 InitializingBean 接口,重写了 afterPropertiesSet 方法,则会调用 afterPropertiesSet 方法,最后还会调用是否指定了 init-method,可以通过 <bean init-method>
标签,或者 @Bean 注解的 initMethod
指定
调用 after… 方法
可以看到 applyBeanPostProcessorsAfterInitialization 方法,该方法与之前的 postProcessBeforeInitialization 方法(第二步)类似,也是循环遍历实现了 BeanPostProcessor 的接口实现类,执行 postProcessAfterInitialization 方法。整个 bean 的生命执行流程就如上面截图所示,哪个接口的方法在哪里被调用,方法的执行流程
第二步的代码如图所示,可以看到只是名字不同而已
最后,对bean的生命流程进行一个流程图的总结
参考文章
Spring 为何需要三级缓存解决循环依赖,而不是二级缓存 - 半分、 - 博客园 (cnblogs.com)
spring中的Aware接口原来是这么回事_spring ware接口-CSDN博客
【死磕 Spring】—– IOC 之 深入分析 Aware 接口-腾讯云开发者社区-腾讯云 (tencent.com)