Spring源码学习(六)-spring初始化回调方法源码学习

1.spring官方指定了三种初始化回调方法
  1.1、@PostConstruct、@PreDestory
  1.2、实现 InitializingBean DisposableBean 接口
  1.3、设置init-method和destory-method
  三种方式的优先级从高到低
在spring官方文档里面有明确指出
1 Multiple lifecycle mechanisms configured for the same bean, with 
2     different initialization methods, are called as follows:
3       Methods annotated with @PostConstruct
4       afterPropertiesSet() as defined by the InitializingBean callback interface
5      A custom configured init() method
6     Destroy methods are called in the same order:
7       Methods annotated with @PreDestroy
8       destroy() as defined by the DisposableBean callback interface
9       A custom configured destroy() method 

 

2.三种配置初始化bean的方式,调用时机不同,对于注解,是在spring生命周期中第七个bean后置处理器调用的时候,由CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization()方法来处理

而剩下的两种是在 第七个bean后置处理器执行之后的下一行代码中执行的 
 
3.@PostConstruct和@PreDestroy源码 
  3.1、在spring生命周期中,第三个后置处理器方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors;在CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法,调用了buildLifecycleMetadata()方法,有一段比较重要的代码: 
  
 1 do {
 2   final List<LifecycleElement> currInitMethods = new ArrayList<>();
 3   final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
 4 
 5   ReflectionUtils.doWithLocalMethods(targetClass, method -> {
 6     //如果目标类中的方法,添加了@PostConstruct注解,就添加到currInitMethods
 7     if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
 8       LifecycleElement element = new LifecycleElement(method);
 9       currInitMethods.add(element);
10       if (logger.isTraceEnabled()) {
11         logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
12       }
13     }
14     //如果目标类的方法,添加了@PreDestory注解,就添加到currDestroyMethod中
15     if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
16       currDestroyMethods.add(new LifecycleElement(method));
17       if (logger.isTraceEnabled()) {
18         logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
19       }
20     }
21   });
22 
23   initMethods.addAll(0, currInitMethods);
24   destroyMethods.addAll(currDestroyMethods);
25   targetClass = targetClass.getSuperclass();
26 }
27 while (targetClass != null && targetClass != Object.class);

这里,最终会根据initMethods和destroyMethods来初始化一个LifecycleMetadata对象,然后再把new出来的元对象,存到了一个map中 lifecycleMetadataCache 
 
 1 private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
 2   if (this.lifecycleMetadataCache == null) {
 3     // Happens after deserialization, during destruction...
 4     return buildLifecycleMetadata(clazz);
 5   }
 6   // Quick check on the concurrent map first, with minimal locking.
 7   LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
 8   if (metadata == null) {
 9     synchronized (this.lifecycleMetadataCache) {
10       metadata = this.lifecycleMetadataCache.get(clazz);
11       if (metadata == null) {
12         metadata = buildLifecycleMetadata(clazz);
13         this.lifecycleMetadataCache.put(clazz, metadata);
14       }
15       return metadata;
16     }
17   }
18   return metadata;
19 }

  3.2、在spring生命周期的第七个后置处理器方法中,org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
会尝试先从lifecycleMetadataCache中根据class,获取到元对象,然后调用元对象的 invokeInitMethods()方法 
  
 1 public void invokeInitMethods(Object target, String beanName) throws Throwable {
 2     Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
 3     Collection<LifecycleElement> initMethodsToIterate =
 4         (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
 5     if (!initMethodsToIterate.isEmpty()) {
 6       boolean debug = logger.isDebugEnabled();
 7       for (LifecycleElement element : initMethodsToIterate) {
 8         if (debug) {
 9           logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());
10         }
11         element.invoke(target);
12       }
13     }
14   }

这里的element.invoke()就是调用bean中添加了@PostConstruct注解的方法(method.invoke())
@PreDestory注解的原理是一样的,只是调用时机是在调用annotationConfigApplicationContext.close()方法的时候,会调用
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeDestruction 
 
4.剩下的两种初始化方法,执行处理逻辑,是在一块代码中 
 
//在调用第七个后置处理器的下一行,是这个代码
  try {
    invokeInitMethods(beanName, wrappedBean, mbd);
  } 
  
 1 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
 2       throws Throwable {
 3 
 4   //判断当前bean是否是 InitializingBean接口的实现类,如果是,判断是否实现了 afterPropertiesSet() 方法
 5   boolean isInitializingBean = (bean instanceof InitializingBean);
 6   if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
 7     if (logger.isTraceEnabled()) {
 8       logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
 9     }
10     if (System.getSecurityManager() != null) {
11       try {
12         AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
13           ((InitializingBean) bean).afterPropertiesSet();
14           return null;
15         }, getAccessControlContext());
16       }
17       catch (PrivilegedActionException pae) {
18         throw pae.getException();
19       }
20     }
21     else {
22       ((InitializingBean) bean).afterPropertiesSet();
23     }
24   }
25 
26   //如果是在@Bean中配置了init-method和destroy-method,那执行的是这里的方法
27   if (mbd != null && bean.getClass() != NullBean.class) {
28     String initMethodName = mbd.getInitMethodName();
29     if (StringUtils.hasLength(initMethodName) &&
30         !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
31         !mbd.isExternallyManagedInitMethod(initMethodName)) {
32       invokeCustomInitMethod(beanName, bean, mbd);
33     }
34   }
35 }

  对于在@Bean注解指定init-method方式的,是在将class扫描到beanDefinition的时候,会对@Bean这种方式的bean进行处理
    loadBeanDefinitionsForBeanMethod(beanMethod);在这里会设置bean的initMethod
  spring扫描bean,将class扫描到beanDefinitionMap中有三种方式;
    @ComponentScan注解
    @Import
        importBeanDefinitionRegistrar
        importSelector
    @Bean 
 
 
5.对于销毁方法,还没仔细研究,后面了解之后,再做补充: 
 
  
 1 public void destroy() {
 2     //这里是处理@PreDestroy注解的销毁方法
 3     if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
 4         for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
 5             processor.postProcessBeforeDestruction(this.bean, this.beanName);
 6         }
 7     }
 8 
 9     if (this.invokeDisposableBean) {
10         if (logger.isTraceEnabled()) {
11             logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
12         }
13         try {
14             if (System.getSecurityManager() != null) {
15                 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
16                     ((DisposableBean) this.bean).destroy();
17                     return null;
18                 }, this.acc);
19             }
20             else {
21                 //这里是处理 DisposableBean 接口实现类中destroy()销毁方法的逻辑
22                 ((DisposableBean) this.bean).destroy();
23             }
24         }
25         catch (Throwable ex) {
26             String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
27             if (logger.isDebugEnabled()) {
28                 logger.warn(msg, ex);
29             }
30             else {
31                 logger.warn(msg + ": " + ex);
32             }
33         }
34     }
35 
36     //这是处理@Bean中 destory-method这种方式的销毁方法
37     if (this.destroyMethod != null) {
38         invokeCustomDestroyMethod(this.destroyMethod);
39     }
40     else if (this.destroyMethodName != null) {
41         Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
42         if (methodToInvoke != null) {
43             invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
44         }
45     }
46 }

 

 
posted @ 2020-01-02 17:11  小小少年-  阅读(887)  评论(0编辑  收藏  举报