【Spring】InitializingBean与DisposableBean接口的实现原理(六)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【Spring】InitializingBean与DisposableBean接⼝的实现原理
(六)
关于在Spring 容器初始化和销毁 bean 前所做的操作有三种⽅式定义:
第⼀种:通过@PostConstruct 和 @PreDestroy ⽅法实现初始化后和销毁bean之前进⾏的操作
第⼆种:通过bean实现InitializingBean和 DisposableBean接⼝
第三种:通过在xml中配置init-method 和 destory-method⽅法,或者配置@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod") 注解
执⾏顺序:@PostConstruct -> InitializingBean -> 配置initMethod -> @PreDestroy -> DisposableBean -> 配置destroyMethod
本章介绍第⼆种
第⼀种见:
⼀、InitializingBean 和 @DisposableBean 接⼝使⽤
1public class BeanPerson implements InitializingBean, DisposableBean {
2
3public void say(String word) {
4 System.out.println("Hello, " + word);
5 }
6
7public BeanPerson() {
8 System.out.println("BeanPerson() ");
9 }
10
11 @Override
12public void afterPropertiesSet() throws Exception {
13 System.out.println("afterPropertiesSet()......");
14 }
15
16 @Override
17public void destroy() throws Exception {
18 System.out.println("destroy()......");
19 }
20
21 }
⼆、原理图
实现原理是通过代码逻辑判断bean的类型,是否实现的对应的接⼝
三、InitializingBean 接⼝实现原理
1、实例化bean时,createBeat()->doCreateBeat()->initializeBean()
初始化 initializeBean() ⽅法如下:
1protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { 2if (System.getSecurityManager() != null) {
3 AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
4 invokeAwareMethods(beanName, bean);
5return null;
6 }, getAccessControlContext());
7 } else {
8// 若bean实现了XXXAware接⼝进⾏⽅法的回调
9 invokeAwareMethods(beanName, bean);
10 }
11
12 Object wrappedBean = bean;
13if (mbd == null || !mbd.isSynthetic()) {
14// ⽀持初始化前bean的后置处理器
15 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
16 }
17
18try {
19// 调⽤初始化⽅法
20 invokeInitMethods(beanName, wrappedBean, mbd);
21 } catch (Throwable ex) {
22throw new BeanCreationException(
23 (mbd != null ? mbd.getResourceDescription() : null),
24 beanName, "Invocation of init method failed", ex);
25 }
26if (mbd == null || !mbd.isSynthetic()) {
27 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
28 }
29
30return wrappedBean;
31 }
2、调⽤了初始化⽅法 invokeInitMethods() ,如下:
1protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
2throws Throwable {
3// 判断容器中是否实现了InitializingBean接⼝
4boolean isInitializingBean = (bean instanceof InitializingBean);
5if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
6if (logger.isTraceEnabled()) {
7 logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
8 }
9if (System.getSecurityManager() != null) {
10try {
11 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
12 ((InitializingBean) bean).afterPropertiesSet();
13return null;
14 }, getAccessControlContext());
15 } catch (PrivilegedActionException pae) {
16throw pae.getException();
17 }
18 } else {
19// 回调实现InitializingBean接⼝的afterPropertiesSet()⽅法
20 ((InitializingBean) bean).afterPropertiesSet();
21 }
22 }
23
24if (mbd != null && bean.getClass() != NullBean.class) {
25// bean定义中看是否有配置的init⽅法
26 String initMethodName = mbd.getInitMethodName();
27// 判断⾃定义的init⽅法名称不叫afterPropertiesSet
28if (StringUtils.hasLength(initMethodName) &&
29 !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
30 !mbd.isExternallyManagedInitMethod(initMethodName)) {
31// 调⽤配置的初始化⽅法
32 invokeCustomInitMethod(beanName, bean, mbd);
33 }
34 }
35 }
其中,判断类bean是否属于InitializingBean接⼝,然后调⽤了afterPropertiesSet()⽅法
四、DisposableBean 接⼝实现原理
1、在容器关闭时,调⽤⽅法链:context.clonse() -> doClose() -> destroyBeans() -> destroySingletons() ->destroySingleton() 销毁单例⽅法 destroySingleton() 如下:
1public void destroySingleton(String beanName) {
2// Remove a registered singleton of the given name, if any.
3// 移除缓存
4 removeSingleton(beanName);
5
6// Destroy the corresponding DisposableBean instance.
7 DisposableBean disposableBean;
8// 加锁
9synchronized (this.disposableBeans) {
10// 根据名称,从需要销毁的是实例集合移除实例,得到disposableBean
11 disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
12 }
13// 销毁bean
14 destroyBean(beanName, disposableBean);
15 }
2、从bean⼯⼚的 disposableBeans 中,获取移除对象,⽽这个 disposableBeans 销毁对象集合中的对象是从注册的时候来的 查看bean创建逻辑: createBeat()->doCreateBeat(),在 doCreateBeat() 调⽤了registerDisposableBeanIfNecessary() ⽅法 1protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
2throws BeanCreationException {
3
4// Instantiate the bean.
5// 实例化的bean会封装成⼀个BeanWrapper对象
6// BeanWrapper是对Bean的包装,其接⼝中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器,
7// 由于BeanWrapper接⼝是PropertyAccessor的⼦接⼝,因此其也可以设置以及访问被包装对象的属性值。
8 BeanWrapper instanceWrapper = null;
9if (mbd.isSingleton()) {
10// 移除⼯⼚bean实例缓存,并获取
11 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
12 }
13if (instanceWrapper == null) {
14// 使⽤合适的实例化策略来创建新的实例:⼯⼚⽅法、构造函数⾃动注⼊、简单初始化该⽅法很复杂也很重要
15 instanceWrapper = createBeanInstance(beanName, mbd, args);
16 }
17// 获取包装Bean中的bean实例
18final Object bean = instanceWrapper.getWrappedInstance();
19// 获取包装Bean中的bean的类clazz对象
20 Class<?> beanType = instanceWrapper.getWrappedClass();
21if (beanType != NullBean.class) {
22// 在bean定义中设置类clazz对象类型
23 mbd.resolvedTargetType = beanType;
24 }
25
26 ......
27
28// Initialize the bean instance.
29// 早起暴露的对象
30 Object exposedObject = bean;
31try {
32// 给的属性进⾏赋值(调⽤set⽅法进⾏赋值)
33 populateBean(beanName, mbd, instanceWrapper);
34// 进⾏对象初始化操作(在这⾥可能⽣成代理对象),调⽤init⽅法
35 exposedObject = initializeBean(beanName, exposedObject, mbd);
36 } catch (Throwable ex) {
37if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
38throw (BeanCreationException) ex;
39 } else {
40throw new BeanCreationException(
41 mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
42 }
43 }
44
45 ......
46
47// Register bean as disposable.
48try {
49// 注册销毁对象
50// 将给定Bean添加到该⼯⼚中的可丢弃Bean列表中,注册器可丢弃Bean接⼝和/或
51// 在⼯⼚关闭时调⽤给定销毁⽅法(如果适⽤)。
只适⽤单例
52 registerDisposableBeanIfNecessary(beanName, bean, mbd);
53 } catch (BeanDefinitionValidationException ex) {
54throw new BeanCreationException(
55 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
56 }
57
58return exposedObject;
59 }
3、注册销毁对象⽅法:registerDisposableBeanIfNecessary()
1protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
2// 如果有安全管理器器,获取其访问控制上下⽂
3 AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
4// 判断是否是⾮多例 && 是否需要在关闭时销毁
5if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
6if (mbd.isSingleton()) {
7// Register a DisposableBean implementation that performs all destruction
8// work for the given bean: DestructionAwareBeanPostProcessors,
9// DisposableBean interface, custom destroy method.
10// 注册⼀个⼀次性Bean实现来执⾏给定Bean的销毁⼯作:DestructionAwareBeanPostProcessors ⼀次性Bean接⼝,
11// ⾃定义销毁⽅法。
12// DisposableBeanAdapter:实际⼀次性Bean和可运⾏接⼝适配器,对给定Bean实例执⾏各种销毁步骤
13// 构建Bean对应的DisposableBeanAdapter对象,与beanName绑定到注册中⼼的⼀次性Bean列表中
14 registerDisposableBean(beanName,
15new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
16 }
17else {
18// A bean with a custom scope...
19 Scope scope = this.scopes.get(mbd.getScope());
20if (scope == null) {
21throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
22 }
23 scope.registerDestructionCallback(beanName,
24new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
25 }
26 }
27 }
4、其中调⽤了registerDisposableBean() ⽅法,并且把原对象和⼀些其他信息封装成了⼀个DisposableBeanAdapter对象,放⼊了⼯⼚的 disposableBeans 集合中
1// 注册需要销毁的是实例
2public void registerDisposableBean(String beanName, DisposableBean bean) {
3synchronized (this.disposableBeans) {
4this.disposableBeans.put(beanName, bean);
5 }
6 }
5、销毁时,从disposableBeans 获取对象,继续从1步骤的 destroyBean() ⽅法,往下⾛
1protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
2// Trigger destruction of dependent beans first...
3 Set<String> dependencies;
4// 移除依赖
5synchronized (this.dependentBeanMap) {
6// Within full synchronization in order to guarantee a disconnected Set
7 dependencies = this.dependentBeanMap.remove(beanName);
8 }
9if (dependencies != null) {
10if (logger.isTraceEnabled()) {
11 logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
12 }
13for (String dependentBeanName : dependencies) {
14 destroySingleton(dependentBeanName);
15 }
16 }
17
18// Actually destroy the bean now...
19// 现在真正销毁
20if (bean != null) {
21try {
22// 调⽤销毁⽅法
23 bean.destroy();
24 }
25catch (Throwable ex) {
26if (logger.isWarnEnabled()) {
27 logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
28 }
29 }
30 }
31
32// Trigger destruction of contained beans...
33 Set<String> containedBeans;
34synchronized (this.containedBeanMap) {
35// Within full synchronization in order to guarantee a disconnected Set
36 containedBeans = this.containedBeanMap.remove(beanName);
37 }
38if (containedBeans != null) {
39for (String containedBeanName : containedBeans) {
40 destroySingleton(containedBeanName);
41 }
42 }
43
44// Remove destroyed bean from other beans' dependencies.
45synchronized (this.dependentBeanMap) {
46for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
47 Map.Entry<String, Set<String>> entry = it.next();
48 Set<String> dependenciesToClean = entry.getValue();
49 dependenciesToClean.remove(beanName);
50if (dependenciesToClean.isEmpty()) {
51 it.remove();
52 }
53 }
54 }
55
56// Remove destroyed bean's prepared dependency information.
57// 移除依赖关系集中对象
58this.dependenciesForBeanMap.remove(beanName);
59 }
6、bean.destroy() ⽅法,这⾥的bean对象是 DisposableBeanAdapter对象如下:
1// 销毁
2 @Override
3public void destroy() {
4if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
5for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
6// 调持销毁前bean的后置处理器
7 processor.postProcessBeforeDestruction(this.bean, this.beanName);
8 }
9 }
10
11// 判断是否实现DisposableBean接⼝
12if (this.invokeDisposableBean) {
13if (logger.isTraceEnabled()) {
14 logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
15 }
16try {
17if (System.getSecurityManager() != null) {
18 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
19 ((DisposableBean) this.bean).destroy();
20return null;
21 }, this.acc);
22 }
23else {
24// 强转,调⽤destroy()⽅法
25 ((DisposableBean) this.bean).destroy();
26 }
27 }
28catch (Throwable ex) {
29 String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
30if (logger.isDebugEnabled()) {
31 logger.warn(msg, ex);
32 }
33else {
34 logger.warn(msg + ": " + ex);
35 }
36 }
37 }
38
39if (this.destroyMethod != null) {
40// 调⽤配置的销毁⽅法
41 invokeCustomDestroyMethod(this.destroyMethod);
42 }
43else if (this.destroyMethodName != null) {
44 Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
45if (methodToInvoke != null) {
46// 调⽤配置的销毁⽅法
47 invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
48 }
49 }
50 }
可以看到其中,判断是否实现DisposableBean接⼝,然后调⽤了((DisposableBean) this.bean).destroy(); this.bean 即是封装前原实例对象,即调⽤了原实例对象的 destroy() ⽅法。