`
yuanke
  • 浏览: 69919 次
  • 性别: Icon_minigender_2
  • 来自: 临沂
社区版块
存档分类
最新评论

Spring中Bean的生命周期详解

阅读更多

Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。

 

Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的?

 

 

 

Bean的生成过程

 

1. 生成BeanDefinition

Spring启动的时候会进行扫描,会先调用

 

Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);

拿到所指定的包路径下的所有文件资源(******.class文件)

 

然后会遍历每个Resource,为每个Resource生成一个MetadataReader对象,这个对象拥有三个功能:

  1. 获取对应的Resource资源
  2. 获取Resource对应的class的元数据信息,包括类的名字、是不是接口、是不是一个注解、是不是抽象类、有没有父类,父类的名字,所实现的所有接口的名字,内部类的类名等等。
  3. 获取Resource对应的class上的注解信息,当前类上有哪些注解,当前类中有哪些方法上有注解

 

在生成MetadataReader对象时,会利用ASM技术解析class文件,得到类的元数据集信息合注解信息,在这个过程中也会利用ClassLoader去加载注解类(ClassUtils.getDefaultClassLoader()所获得的类加载器),但是不会加载本类。

 

有了MetadataReader对象,就相当于有了当前类的所有信息,但是当前类并没有加载,也是可以理解的,真正在用到这个类的时候才加载。

 

然后利用MetadataReader对象生成一个ScannedGenericBeanDefinition对象,注意此时的BeanDefinition对象中的beanClass属性存储的是当前类的名字,而不是class对象。(beanClass属性的类型是Object,它即可以存储类的名字,也可以存储class对象)

 

2. 合并BeanDefinition

 

如果某个BeanDefinition存在父BeanDefinition,那么则要进行合并

3. 加载类

 

有了BeanDefinition之后,后续就会基于BeanDefinition去创建Bean,而创建Bean就必须实例化对象,而实例化就必须先加载当前BeanDefinition所对应的class,在AbstractAutowireCapableBeanFactory类的createBean()方法中,一开始就会调用:

 

Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

这行代码就是去加载类,该方法是这么实现的:

 

if (mbd.hasBeanClass()) {
    return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
    return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
        doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
    }
else {
    return doResolveBeanClass(mbd, typesToMatch);
}

 

 

public boolean hasBeanClass() {
    return (this.beanClass instanceof Class);
}

如果beanClass属性的类型是Class,那么就直接返回,如果不是,则会根据类名进行加载(doResolveBeanClass方法所做的事情)

 

会利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来加载。

 

ClassUtils.getDefaultClassLoader()

  1. 优先获取当前线程中的ClassLoader
  2. 如果为空,则获取加载ClassUtils类的类加载器(正常情况下,就是AppClassLoader,但是如果是在Tomcat中运行,那么则会是Tomcat中为每个应用所创建的WebappClassLoader)
  3. 如果为空,那么则是bootstrap类加载器加载的ClassUtils类,那则获取系统类加载器进行加载

 

4. 实例化前

允许第三方可以不按照Spring的正常流程来创建一个Bean,可以利用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法来提前返回一个Bean对象,直接结束Bean的生命周期

5. 推断构造方法

单独讲

6. 实例化

构造方法反射得到一个实例

7. BeanDefinition的后置处理

 

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof MergedBeanDefinitionPostProcessor) {
        MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
        bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    }
}

这里可以处理BeanDefinition,但是此时实例对象已经生成好了,所以修改beanClass已经没用了,但是可以修改PropertyValues,比如:

 

@Component
public class LubanMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (beanName.equals("userService")) {
            beanDefinition.setBeanClass(User.class); // 没用
            beanDefinition.getPropertyValues().add("name","xxx");
        }
    }
}

 

 

8. 填充属性

单独讲

9. 执行Aware

  1. ((BeanNameAware) bean).setBeanName(beanName);
  2. ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
  3. ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);

 

 

10. 初始化前

 

for (BeanPostProcessor processor : getBeanPostProcessors()) {
    Object current = processor.postProcessBeforeInitialization(result, beanName);
    if (current == null) {
        return result;
    }
    result = current;
}

 

11. 初始化

  1. ((InitializingBean) bean).afterPropertiesSet();
  2. 执行BeanDefinition中指定的初始化方法

12. 初始化后

 

for (BeanPostProcessor processor : getBeanPostProcessors()) {
    Object current = processor.postProcessAfterInitialization(result, beanName);
    if (current == null) {
        return result;
    }
    result = current;
}

 

Bean的销毁过程

1. 容器关闭

2. 发布ContextClosedEvent事件

3. 调用LifecycleProcessor的onClose方法

4. 销毁单例Bean

  1. 找出所有DisposableBean(实现了DisposableBean接口的Bean)
  2. 遍历每个DisposableBean
  3. 找出依赖了当前DisposableBean的其他Bean,将这些Bean从单例池中移除掉
  4. 调用DisposableBean的destroy()方法
  5. 找到当前DisposableBean所包含的inner beans,将这些Bean从单例池中移除掉 (inner bean参考https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-inner-beans)

 

这里涉及到一个设计模式:适配器模式

 

在销毁时,Spring会找出实现了DisposableBean接口的Bean。

 

但是我们在定义一个Bean时,如果这个Bean实现了DisposableBean接口,或者实现了AutoCloseable接口,或者在BeanDefinition中指定了destroyMethodName,那么这个Bean都属于“DisposableBean”,这些Bean在容器关闭时都要调用相应的销毁方法。

 

所以,这里就需要进行适配,将实现了DisposableBean接口、或者AutoCloseable接口等适配成实现了DisposableBean接口,所以就用到了DisposableBeanAdapter。

 

会把实现了AutoCloseable接口的类封装成DisposableBeanAdapter,而DisposableBeanAdapter实现了DisposableBean接口。

分享到:
评论

相关推荐

    详解Spring中Bean的生命周期和作用域及实现方式

    主要给大家介绍了Spring中Bean的生命周期和作用域及实现方式的相关资料,文中介绍的非常详细,对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。

    spring之Bean的生命周期详解

    本篇文章主要介绍了spring之Bean的生命周期详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    spring中bean的生命周期详解

    今天小编就为大家分享一篇关于spring中bean的生命周期详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

    详解Spring中bean生命周期回调方法

    本篇文章主要介绍了详解Spring中bean生命周期回调方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Spring Bean的生命周期详细介绍

    主要介绍了Spring Bean的生命周期的相关资料,需要的朋友可以参考下

    Spring配置使用之Bean生命周期详解

    主要介绍了Spring配置使用之Bean生命周期详解,具有一定参考价值,需要的朋友可以了解下。

    Spring与bean有关的生命周期示例详解

    主要给大家介绍了关于Spring与bean有关的生命周期的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

    Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等).doc

    Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等).doc

    详解Java的Spring框架中bean的定义以及生命周期

    主要介绍了Java的Spring框架中bean的定义以及生命周期,bean的实例化是Java web开发中的重要基础,需要的朋友可以参考下

    Spring中Bean的讲解

    自动装配四.Bean的生命周期 一.Bean的简介 Spring 官方文档对 bean 的解释是: In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are

    spring2.5学习PPT 传智博客

    06_Spring管理的Bean的生命周期 07_编码剖析Spring依赖注入的原理 08_编码剖析Spring装配基本属性的原理 09_Spring如何装配各种集合类型的属性 10_使用构造器装配属性 11_用@Resource注解完成属性装配 12_...

    Spring生命周期回调与容器扩展详解

    主要介绍了Spring生命周期回调与容器扩展详解,具有一定借鉴价值,需要的朋友可以参考下。

    Spring-Reference_zh_CN(Spring中文参考手册)

    7.3.1. 通知的生命周期 7.3.2. Spring里的通知类型 7.3.2.1. 拦截around通知 7.3.2.2. 前置通知 7.3.2.3. 异常通知 7.3.2.4. 后置通知 7.3.2.5. 引入通知 7.4. Spring里的advisor(Advisor) API 7.5. 使用...

    Spring中文帮助文档

    3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 ...

    Spring.3.x企业应用开发实战(完整版).part2

    3.5.2 ApplicationContext中Bean的生命周期 3.6 小结 第4章 在IoC容器中装配Bean 4.1 Spring配置概述 4.1.1 Spring容器高层视图 4.1.2 基于XML的配置 4.2 Bean基本配置 4.2.1 装配一个Bean 4.2.2 Bean的命名 4.3 ...

    Spring 2.0 开发参考手册

    7.3.1. 通知的生命周期 7.3.2. Spring里的通知类型 7.4. Spring里的advisor(Advisor) API 7.5. 使用ProxyFactoryBean创建AOP代理 7.5.1. 基础 7.5.2. JavaBean属性 7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对...

    Spring API

    3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 ...

    Spring3.x企业应用开发实战(完整版) part1

    3.5.2 ApplicationContext中Bean的生命周期 3.6 小结 第4章 在IoC容器中装配Bean 4.1 Spring配置概述 4.1.1 Spring容器高层视图 4.1.2 基于XML的配置 4.2 Bean基本配置 4.2.1 装配一个Bean 4.2.2 Bean的命名 4.3 ...

Global site tag (gtag.js) - Google Analytics