• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
流浪JAVA
唯余岩下多情水,犹解年年傍驿流。
博客园    首页    新随笔    联系   管理    订阅  订阅
Spring Bean的生命周期

  上次我们说了Spring在解决循环引用时采用的三级缓存,以达成bean的提前曝光来解决循环引用问题。那么对于一个bean在Spring中是如何走过它平凡却又不平庸的一生的呢?来上一张借来的图片先看一看,在奶袋里有一个简略印象,然后听我扯一扯。

 好的,还是从我们运行如下代码,获取一个user bean 开始我们的故事:

1 ClassPathResource resource = new ClassPathResource("bean.xml");
2 DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
3 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
4 reader.loadBeanDefinitions(resource);
5 UserBean user = (UserBean) factory.getBean("user");

在启动spring第一次获取user bean 单例时,会触发spring的实例化进程。getBean()方法是实例化的入口方法,真正执行实例化进程的是AbstractAutowireCapableBeanFactory.createBean()中执行的doCreateBean()方法。

 1   protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
 2             throws BeanCreationException {
 3 
 4         // Instantiate the bean.
 5         BeanWrapper instanceWrapper = null;
 6         if (mbd.isSingleton()) {
 7             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
 8         }
 9         if (instanceWrapper == null) {
10             instanceWrapper = createBeanInstance(beanName, mbd, args);  //创建bean实例
11         }
12         final Object bean = instanceWrapper.getWrappedInstance();
13         Class<?> beanType = instanceWrapper.getWrappedClass();
14         if (beanType != NullBean.class) {
15             mbd.resolvedTargetType = beanType;
16         }
17 
18         // Allow post-processors to modify the merged bean definition.
19         synchronized (mbd.postProcessingLock) {
20             if (!mbd.postProcessed) {
21                 try {
22                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
23                 }
24                 catch (Throwable ex) {
25                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
26                             "Post-processing of merged bean definition failed", ex);
27                 }
28                 mbd.postProcessed = true;
29             }
30         }
31 
32         // Eagerly cache singletons to be able to resolve circular references
33         // even when triggered by lifecycle interfaces like BeanFactoryAware.
34         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
35                 isSingletonCurrentlyInCreation(beanName));
36         if (earlySingletonExposure) {
37             if (logger.isTraceEnabled()) {
38                 logger.trace("Eagerly caching bean '" + beanName +
39                         "' to allow for resolving potential circular references");
40             }
41             addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
42         }
43 
44         // Initialize the bean instance.
45         Object exposedObject = bean;
46         try {
47             populateBean(beanName, mbd, instanceWrapper);  //填充bean实例,包括设置bean属性值(注入属性对象等)
48             exposedObject = initializeBean(beanName, exposedObject, mbd);  //在此调用执行初始化bean
49         }
50         catch (Throwable ex) {
51             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
52                 throw (BeanCreationException) ex;
53             }
54             else {
55                 throw new BeanCreationException(
56                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
57             }
58         }
59 
60         if (earlySingletonExposure) {
61             Object earlySingletonReference = getSingleton(beanName, false);
62             if (earlySingletonReference != null) {
63                 if (exposedObject == bean) {
64                     exposedObject = earlySingletonReference;
65                 }
66                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
67                     String[] dependentBeans = getDependentBeans(beanName);
68                     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
69                     for (String dependentBean : dependentBeans) {
70                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
71                             actualDependentBeans.add(dependentBean);
72                         }
73                     }
74                     if (!actualDependentBeans.isEmpty()) {
75                         throw new BeanCurrentlyInCreationException(beanName,
76                                 "Bean with name '" + beanName + "' has been injected into other beans [" +
77                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
78                                 "] in its raw version as part of a circular reference, but has eventually been " +
79                                 "wrapped. This means that said other beans do not use the final version of the " +
80                                 "bean. This is often the result of over-eager type matching - consider using " +
81                                 "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
82                     }
83                 }
84             }
85         }
86 
87         // Register bean as disposable.
88         try {
89             registerDisposableBeanIfNecessary(beanName, bean, mbd);  //注册执行销毁的DisposableBean如果需要的话
90         }
91         catch (BeanDefinitionValidationException ex) {
92             throw new BeanCreationException(
93                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
94         }
95 
96         return exposedObject;
97     }

通过追踪上面doCreateBean()方法,我可以看到在bean实例化完成后调用populateBean()来对实例化后的user 对象(bean)进行填充,其主要是完成了user属性的设置。而后执行initializeBean()来完成对实例化后的bean完成后续的初始化工作。看下面代码:

 1   protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
 2         if (System.getSecurityManager() != null) {
 3             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
 4                 invokeAwareMethods(beanName, bean);
 5                 return null;
 6             }, getAccessControlContext());
 7         }
 8         else {
 9             invokeAwareMethods(beanName, bean);  //检查执行、激活aware
10         }
11 
12         Object wrappedBean = bean;
13         if (mbd == null || !mbd.isSynthetic()) {
14             wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  //执行BeanPostProcesser增强的前置处理
15         }
16 
17         try {
18             invokeInitMethods(beanName, wrappedBean, mbd);  
19         }
20         catch (Throwable ex) {
21             throw new BeanCreationException(
22                     (mbd != null ? mbd.getResourceDescription() : null),
23                     beanName, "Invocation of init method failed", ex);
24         }
25         if (mbd == null || !mbd.isSynthetic()) {
26             wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  //执行BeanPostProcesser增强的后置处理
27         }
28 
29         return wrappedBean;
30     }

我在上面的initializeBean()方法中看到,在对bean进行初始化之前首先调用下面invokeAwareMethods()方法,通过一系列的判断来检查当前的user bean是否实现了一系列的aware接口,并激活其实现的方法。这一阶段主要感知的是BeanNameAware、BeanClassLoaderAware、BeanFactoryAware :

  • BeanNameAware:对该 bean 对象定义的 beanName 设置到当前对象实例中
  • BeanClassLoaderAware:将当前 bean 对象相应的 ClassLoader 注入到当前对象实例中
  • BeanFactoryAware:BeanFactory 容器会将自身注入到当前对象实例中,这样当前对象就会拥有一个 BeanFactory 容器的引用。
 1   private void invokeAwareMethods(final String beanName, final Object bean) {
 2         if (bean instanceof Aware) {
 3             if (bean instanceof BeanNameAware) {
 4                 ((BeanNameAware) bean).setBeanName(beanName);
 5             }
 6             if (bean instanceof BeanClassLoaderAware) {
 7                 ClassLoader bcl = getBeanClassLoader();
 8                 if (bcl != null) {
 9                     ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
10                 }
11             }
12             if (bean instanceof BeanFactoryAware) {
13                 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
14             }
15         }
16     }

而后,是执行BeanPostProcesser对bean的增强。在BeanPostProcesser前后置增强方法之间执行的是下面初始化方法,看源码注释。以我英语三级60分的半瓶子水给大家解释一下就是:给传进来的这个bean一个机会响应现在它所有的属性都被设置完成了,和另一个去感知自己拥有的bean factory 的机会。这个意思就是我要检查一下它是不是实现了InitializingBean接口或者自定义了init method,如果需要我就执行一下子。总结来说就两点,一是检查user是不是实现了InitializingBean这个接口,这个接口中有一个afterPropertiesSet()方法,实现了就执行一下这个方法完成一些初始化工作。再就是检查一下,用户是不是配置了自定义的init-method方法,配置了就通过反射的方式调用一下完成用户自定义的初始化。

 1   /**
 2      * Give a bean a chance to react now all its properties are set,
 3      * and a chance to know about its owning bean factory (this object).
 4      * This means checking whether the bean implements InitializingBean or defines
 5      * a custom init method, and invoking the necessary callback(s) if it does.
 6      * @param beanName the bean name in the factory (for debugging purposes)
 7      * @param bean the new bean instance we may need to initialize
 8      * @param mbd the merged bean definition that the bean was created with
 9      * (can also be {@code null}, if given an existing bean instance)
10      * @throws Throwable if thrown by init methods or by the invocation process
11      * @see #invokeCustomInitMethod
12      */
13     protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
14             throws Throwable {
15 
16         boolean isInitializingBean = (bean instanceof InitializingBean);  //是否实现了InitializingBean
17         if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {  
18             if (logger.isTraceEnabled()) {
19                 logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
20             }
21             if (System.getSecurityManager() != null) {
22                 try {
23                     AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
24                         ((InitializingBean) bean).afterPropertiesSet();
25                         return null;
26                     }, getAccessControlContext());
27                 }
28                 catch (PrivilegedActionException pae) {
29                     throw pae.getException();
30                 }
31             }
32             else {
33                 ((InitializingBean) bean).afterPropertiesSet();
34             }
35         }
36 
37         if (mbd != null && bean.getClass() != NullBean.class) {
38             String initMethodName = mbd.getInitMethodName();
39             if (StringUtils.hasLength(initMethodName) &&
40                     !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
41                     !mbd.isExternallyManagedInitMethod(initMethodName)) {  //有没有自定义 init method
42                 invokeCustomInitMethod(beanName, bean, mbd);
43             }
44         }
45     }

到此你要的bean就准备好了,你可以用它来做你想让它干的事儿了。做完你给它的作业,并不会立即调用销毁的方法,因为这时候spring容器还在运行,只有当spring容器关闭的时候才会执行。但是销毁的方法,spring不会自动去调用,需要我们来手动做一些操作去通知spring容器调用这些方法。对于BeanFactory容器,我们可以通过主动调用destorySingletons()通知 BeanFactory 容器去执行相应的销毁方法。如果是ApplicationContext 容器则调用registerShutdownHook() 方法.

所要执行的销毁方法和InitializingBean 和 init-method 用于对象的自定义初始化工作是类似的。首先判断是否实现了DisposableBean接口,然后是否配置了destroy-method方法来自定义销毁工作。

 最后,我们看一下BeanFactory容器是如何执行destorySingletons()方法的,代码如下:

 1   public void destroySingletons() {
 2         if (logger.isTraceEnabled()) {
 3             logger.trace("Destroying singletons in " + this);
 4         }
 5         synchronized (this.singletonObjects) {
 6             this.singletonsCurrentlyInDestruction = true;
 7         }
 8 
 9         String[] disposableBeanNames;
10         synchronized (this.disposableBeans) {
11             disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());  //获取所有注册了DisposableBeans的beanName
12         }
13         for (int i = disposableBeanNames.length - 1; i >= 0; i--) { //遍历执行
14             destroySingleton(disposableBeanNames[i]);
15         }
16 
17         this.containedBeanMap.clear();
18         this.dependentBeanMap.clear();
19         this.dependenciesForBeanMap.clear();
20 
21         clearSingletonCache();
22     }

 

posted on 2020-09-04 16:34  寻说  阅读(260)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3