@@ -325,27 +325,110 @@ prototype 作用域下,每次获取都会创建一个新的 bean 实例,不
325
325
326
326
### Bean 的生命周期了解么?
327
327
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 )
349
432
350
433
## Spring AOP
351
434
0 commit comments