@@ -325,27 +325,110 @@ prototype 作用域下,每次获取都会创建一个新的 bean 实例,不
325325
326326### Bean 的生命周期了解么?
327327
328- - Bean 容器找到配置文件中 Spring Bean 的定义。
329- - Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
330- - 如果涉及到一些属性值 利用 ` set() ` 方法设置一些属性值。
331- - 如果 Bean 实现了 ` BeanNameAware ` 接口,调用 ` setBeanName() ` 方法,传入 Bean 的名字。
332- - 如果 Bean 实现了 ` BeanClassLoaderAware ` 接口,调用 ` setBeanClassLoader() ` 方法,传入 ` ClassLoader ` 对象的实例。
333- - 如果 Bean 实现了 ` BeanFactoryAware ` 接口,调用 ` setBeanFactory() ` 方法,传入 ` BeanFactory ` 对象的实例。
334- - 与上面的类似,如果实现了其他 ` *.Aware ` 接口,就调用相应的方法。
335- - 如果有和加载这个 Bean 的 Spring 容器相关的 ` BeanPostProcessor ` 对象,执行` postProcessBeforeInitialization() ` 方法
336- - 如果 Bean 实现了` InitializingBean ` 接口,执行` afterPropertiesSet() ` 方法。
337- - 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
338- - 如果有和加载这个 Bean 的 Spring 容器相关的 ` BeanPostProcessor ` 对象,执行` postProcessAfterInitialization() ` 方法
339- - 当要销毁 Bean 的时候,如果 Bean 实现了 ` DisposableBean ` 接口,执行 ` destroy() ` 方法。
340- - 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
341-
342- 图示:
343-
344- ![ Spring Bean 生命周期] ( https://images.xiaozhuanlan.com/photo/2019/24bc2bad3ce28144d60d9e0a2edf6c7f.jpg )
345-
346- 与之比较类似的中文版本:
347-
348- ![ Spring Bean 生命周期] ( https://images.xiaozhuanlan.com/photo/2019/b5d264565657a5395c2781081a7483e1.jpg )
328+ 1 . ** 创建 Bean 的实例** :Bean 容器首先会找到配置文件中的 Bean 定义,然后使用 Java 反射 API 来创建 Bean 的实例。
329+ 2 . ** Bean 属性赋值/填充** :为 Bean 设置相关属性和依赖,例如` @Autowired ` 等注解注入的对象、` @Value ` 注入的值、` setter ` 方法或构造函数注入依赖和值、` @Resource ` 注入的各种资源。
330+ 3 . ** Bean 初始化** :
331+ - 如果 Bean 实现了 ` BeanNameAware ` 接口,调用 ` setBeanName() ` 方法,传入 Bean 的名字。
332+ - 如果 Bean 实现了 ` BeanClassLoaderAware ` 接口,调用 ` setBeanClassLoader() ` 方法,传入 ` ClassLoader ` 对象的实例。
333+ - 如果 Bean 实现了 ` BeanFactoryAware ` 接口,调用 ` setBeanFactory() ` 方法,传入 ` BeanFactory ` 对象的实例。
334+ - 与上面的类似,如果实现了其他 ` *.Aware ` 接口,就调用相应的方法。
335+ - 如果有和加载这个 Bean 的 Spring 容器相关的 ` BeanPostProcessor ` 对象,执行` postProcessBeforeInitialization() ` 方法
336+ - 如果 Bean 实现了` InitializingBean ` 接口,执行` afterPropertiesSet() ` 方法。
337+ - 如果 Bean 在配置文件中的定义包含 ` init-method ` 属性,执行指定的方法。
338+ - 如果有和加载这个 Bean 的 Spring 容器相关的 ` BeanPostProcessor ` 对象,执行` postProcessAfterInitialization() ` 方法。
339+ 4 . ** 销毁 Bean** :销毁并不是说要立马把 Bean 给销毁掉,而是把 Bean 的销毁方法先记录下来,将来需要销毁 Bean 或者销毁容器的时候,就调用这些方法去释放 Bean 所持有的资源。
340+ - 如果 Bean 实现了 ` DisposableBean ` 接口,执行 ` destroy() ` 方法。
341+ - 如果 Bean 在配置文件中的定义包含 ` destroy-method ` 属性,执行指定的 Bean 销毁方法。或者,也可以直接通过` @PreDestroy ` 注解标记 Bean 销毁之前执行的方法。
342+
343+ ` AbstractAutowireCapableBeanFactory ` 的 ` doCreateBean() ` 方法中能看到依次执行了这 4 个阶段:
344+
345+ ``` java
346+ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object [] args)
347+ throws BeanCreationException {
348+
349+ // 1. 创建 Bean 的实例
350+ BeanWrapper instanceWrapper = null ;
351+ if (instanceWrapper == null ) {
352+ instanceWrapper = createBeanInstance(beanName, mbd, args);
353+ }
354+
355+ Object exposedObject = bean;
356+ try {
357+ // 2. Bean 属性赋值/填充
358+ populateBean(beanName, mbd, instanceWrapper);
359+ // 3. Bean 初始化
360+ exposedObject = initializeBean(beanName, exposedObject, mbd);
361+ }
362+
363+ // 4. 销毁 Bean-注册回调接口
364+ try {
365+ registerDisposableBeanIfNecessary(beanName, bean, mbd);
366+ }
367+
368+ return exposedObject;
369+ }
370+ ```
371+
372+ ` Aware ` 接口能让 Bean 能拿到 Spring 容器资源。
373+
374+ Spring 中提供的 ` Aware ` 接口主要有:
375+
376+ 1 . ` BeanNameAware ` :注入当前 bean 对应 beanName;
377+ 2 . ` BeanClassLoaderAware ` :注入加载当前 bean 的 ClassLoader;
378+ 3 . ` BeanFactoryAware ` :注入当前 ` BeanFactory ` 容器的引用。
379+
380+ ` BeanPostProcessor ` 接口是 Spring 为修改 Bean 提供的强大扩展点。
381+
382+ ``` java
383+ public interface BeanPostProcessor {
384+
385+ // 初始化前置处理
386+ default Object postProcessBeforeInitialization (Object bean , String beanName ) throws BeansException {
387+ return bean;
388+ }
389+
390+ // 初始化后置处理
391+ default Object postProcessAfterInitialization (Object bean , String beanName ) throws BeansException {
392+ return bean;
393+ }
394+
395+ }
396+ ```
397+
398+ - ` postProcessBeforeInitialization ` :Bean 实例化、属性注入完成后,` InitializingBean#afterPropertiesSet ` 方法以及自定义的 ` init-method ` 方法之前执行;
399+ - ` postProcessAfterInitialization ` :类似于上面,不过是在 ` InitializingBean#afterPropertiesSet ` 方法以及自定义的 ` init-method ` 方法之后执行。
400+
401+ ` InitializingBean ` 和 ` init-method ` 是 Spring 为 Bean 初始化提供的扩展点。
402+
403+ ``` java
404+ public interface InitializingBean {
405+ // 初始化逻辑
406+ void afterPropertiesSet () throws Exception ;
407+ }
408+ ```
409+
410+ 指定 ` init-method ` 方法,指定初始化方法:
411+
412+ ``` xml
413+ <?xml version =" 1.0" encoding =" UTF-8" ?>
414+ <beans xmlns =" http://www.springframework.org/schema/beans"
415+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
416+ xsi : schemaLocation =" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
417+
418+ <bean id =" demo" class =" com.chaycao.Demo" init-method =" init()" />
419+
420+ </beans >
421+ ```
422+
423+ ** 如何记忆呢?**
424+
425+ 1 . 整体上可以简单分为四步:实例化 —> 属性赋值 —> 初始化 —> 销毁。
426+ 2 . 初始化这一步涉及到的步骤比较多,包含 ` Aware ` 接口的依赖注入、` BeanPostProcessor ` 在初始化前后的处理以及 ` InitializingBean ` 和 ` init-method ` 的初始化操作。
427+ 3 . 销毁这一步会注册相关销毁回调接口,最后通过` DisposableBean ` 和 ` destory-method ` 进行销毁。
428+
429+ 最后,再分享一张清晰的图解(图源:[ 如何记忆 Spring Bean 的生命周期] ( https://chaycao.github.io/2020/02/15/如何记忆Spring-Bean的生命周期.html ) )。
430+
431+ ![ ] ( https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/spring-bean-lifestyle.png )
349432
350433## Spring AOP
351434
0 commit comments