精华内容
下载资源
问答
  • Spring的Bean生命周期
    千次阅读
    2022-01-08 19:28:30

    什么是 Spring Bean 的生命周期

    对于普通的 Java 对象,当 new 的时候创建对象,然后该对象就能够使用了。一旦该对象不再被使用,则由 Java 自动进行垃圾回收。

    而 Spring 中的对象是 bean,bean 和普通的 Java 对象没啥大的区别,只不过 Spring 不再自己去 new 对象了,而是由 IoC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IoC 容器要即可。IoC 其实就是解决对象之间的耦合问题,Spring Bean 的生命周期完全由容器控制。

    Bean的生命周期

    Spring bean的生命周期阶段是:

    bean定义

    bean注册

    实列化

    依赖注入

    初始化

    销毁

    • 1.bean定义:就是从xml或注解定位资源加载读取bean的元信息并定义成一个BeanDefinition对象
    • 2.bean注册:将BeanDefinition对象根据相应的规则放到缓存池map中
    • 3.实例化:根据BeanDefinition实例化真正的bean,即是调用构造函数
    • 4.依赖注入:属性赋值调用setter方法,即是依赖注入(DI)
    • 5.初始化: 初始化是用户能自定义扩展的阶段
    • 6.销毁: 销毁是用户能自定义扩展的阶段

    注:其他都是在这阶段前后的扩展点

    Spring角度查看bean的定义与注册

    refresh()

    public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
             // 准备Bean初始化相关的环境信息,其内部提供了一个空实现的initPropertySources()方法用于提供给用户一个更改相关环境信息的机会
            this.prepareRefresh();
            // 创建BeanFactory实例,并且注册相关的bean信息
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            // 注册Aware和Processor实例,并且注册了后续处理请求所需的一些Editor信息
            this.prepareBeanFactory(beanFactory);
    
            try {
                // 提供的一个空方法,用于供给子类对已经生成的BeanFactory的一些信息进行定制
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                // 调用BeanFactoryPostProcessor及其子接口的相关方法,这些接口提供了一个入口,提供给了调用方一个修改已经生成的BeanDefinition的入口
                this.invokeBeanFactoryPostProcessors(beanFactory);
                // 对BeanPostProcessor进行注册
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                // 初始化国际化所需的bean信息
                this.initMessageSource();
                // 初始化事件广播器的bean信息
                this.initApplicationEventMulticaster();
                // 提供的一个空方法,供给子类用于提供自定义的bean信息,或者修改已有的bean信息
                this.onRefresh();
                // 注册事件监听器
                this.registerListeners();
                 // 对已经注册的非延迟(配置文件指定)bean的实例化
                this.finishBeanFactoryInitialization(beanFactory);
                // 清除缓存的资源信息,初始化一些声明周期相关的bean,并且发布Context已被初始化的事件
                this.finishRefresh();
            } catch (BeansException var10) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
                }
                 // 发生异常则销毁已经生成的bean
                this.destroyBeans();
                // 重置refresh字段信息
                this.cancelRefresh(var10);
                throw var10;
            } finally {
                // 初始化一些缓存信息
                this.resetCommonCaches();
                contextRefresh.end();
            }
    
        }
    }

    SpringBoot角度查看bean定义和注册

    1. 自动加载配置类

    2. bean定义和注册

    注:springboot只是比spring多了自动配置相关流程,在spring上做了一层逻辑封装。

    实例化,依赖注入,初始化

    AbstractAutowireCapableBeanFactory为AutowireCapableBeanFactory接口的一个实现类,其中AbstractAutowireCapableBeanFactory实现类的一个方法doCreateBean()

    //位置:AbstractAutowireCapableBeanFactory#doCreateBean
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
    
        if (instanceWrapper == null) {
        	// 实例化阶段
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }
    
        ...
    
        Object exposedObject = bean;
    
        try {
        	// 依赖注入,属性赋值阶段
            this.populateBean(beanName, mbd, instanceWrapper);
            // 初始化阶段
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            ...
        }
    
        ...
    }

    可以发现,分别调用三种方法:

    1. createBeanInstance() -> 实例化
    2. populateBean() -> 依赖注入
    3. initializeBean() -> 初始化

    销毁

    销毁阶段是在容器关闭时调用的,在ConfigurableApplicationContext#close()

    至于xxxAware,BeanPostProcessor,BeanFactoryPostProcessor等类,只不过是对主流程的一系列扩展点而已。

    Bean的生命周期的扩展点

    Spring Bean 的生命周期的扩展点很多,这里不可能全部列出来,只说核心的扩展点。这也就是为什么 Spring 的扩展性很好的原因,开了很多的口子,尽可能让某个功能高内聚松耦合,用户需要哪个功能就用哪个,而不是直接来一个大而全的东西。

    Bean级别

    这些接口的实现类是基于 Bean 的,只要实现了这些接口的Bean才起作用

    • BeanNameAware
    • BeanFactoryAware
    • ApplicationContextAware
    • InitializingBean
    • DisposableBean

    还要很多的xxxAware,这些不常用,下面生命周期测试就不加上,如:

    • BeanClassLoaderAware
    • EnvironmentAware
    • EmbeddedValueResolverAware
    • ResourceLoaderAware
    • ApplicationEventPublisherAware
    • MessageSourceAware
    • ServletContextAware

    容器级别

    这些接口的实现类是独立于 Bean 的,并且会注册到 Spring 容器中。一般称它们的实现类为后置处理器。

    在 Spring 容器创建任何 Bean 的时候,这些后置处理器都会发生作用

    • BeanPostProcessor
    • InstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor 是继承了 BeanPostProcessor)
    • 工厂后处理器接口也是容器级的。在应用上下文装配配置文件之后立即调用:
      • AspectJWeavingEnabler
      • ConfigurationClassPostProcessor
      • CustomAutowireConfigurer

    常用接口

    InstantiationAwareBeanPostProcessor

    • 该类是 BeanPostProcessor 的子接口,常用的有如下三个方法:
      • postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用
      • postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、设置属性前调用
      • postProcessAfterInstantiation(Class beanClass, String beanName):在bean实例化之后调用

    BeanNameAware

    • BeanNameAware接口是为了让自身Bean能够感知到,只有一个方法setBeanName(String name),获取到自身在Spring容器中的id或name属性。

    BeanFactoryAware

    • 该接口只有一个方法setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory,可以对工厂中的所有bean进行扩展。

    ApplicationContextAware

    • 该接口只有一个方法setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext,可以对整个容器进行扩展。
    • 注:有时候并不会调用该接口,这要根据你的IOC容器来决定:Spring IOC容器最低要求是实现BeanFactory接口,而不是实现ApplicationContext接口,对于那些没有实现ApplicationContext接口的容器,在生命周期对应的ApplicationContextAware定义的方法也是不会调用的,只要实现了ApplicationContext接口的容器,才会调用。

    BeanPostProcessor

    • postProcessBeforeInitialization(Object bean, String beanName):在初始化之前调用此方法,Spring 的 AOP 就是利用它实现的。
    • postProcessAfterInitialization(Object bean, String beanName):在初始化之后调用此方法

    InitializingBean

    • 该接口只有一个方法afterPropertiesSet(),在属性注入完成后调用
    • 凡是继承该接口的类,在初始化bean的时候都会执行该方法,可以进行一些属性配置等工作。
    • InitializingBean 对应生命周期的初始化阶段,在源码的invokeInitMethods(beanName, wrappedBean, mbd)方法中调用。

    DisposableBean

    • 该接口的作用是在对象销毁时调用,可以做一些资源销毁操作。
    • DisposableBean 类似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了DisposableBean接口的Bean然后调用其destroy()方法

    常用注解

    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")

    • @Bean声明一个bean,配合@Configuration注解使用
    • initMethod:声明bean初始化时回调一个方法,该方法需要程序员编写
    • destroyMethod:声明bean销毁时回调一个方法,该方法需要程序员编写

    @PostConstruct

    • bean的一个基于注解的初始化方法

    @PreDestroy

    • bean的一个基于注解的销毁方法

    案例分析

    声明一个bean

    @Configuration
    public class BeanInitAndDestroyConfig {
    
        /**
         * @return 这里没有指定bean名字,默认是方法名
         */
        @Description("测试bean的生命周期")
        @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
        public MyService myServiceBeanName() {//入参数可注入其他依赖
            return new MyService();
        }
    }
    • 声明一个名为:myServiceBeanName的bean
    • initMethod:bean的初始化方法为:initMethod
    • destroyMethod:bean的销毁方法为:destroyMethod

    Animal实现类

    • 这里只是想用来说明 @Qualifier注解能根据bean名称匹配。

    我的服务类

    • 即是针对当前bean只调用一次的接口
    /**
     * @Description: bean生命周期测试:这些接口只针对当前bean
     * @Author: jianweil
     * @date: 2021/12/8 9:46
     */
    public class MyService implements Person, BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
    
        private Animal animal = null;
    
        private ApplicationContext applicationContext;
    
        /**
         *接口规定方法
         */
        @Override
        public void service() {
            this.animal.use();
        }
    
        public MyService() {
            System.out.println("2. [bean实例化]:"+this.getClass().getSimpleName()+"----------构造方法");
        }
        /**
         *接口规定方法:注入依赖
         */
        @Override
        @Autowired
        @Qualifier("dog")
        public void setAnimal(Animal animal) {
            System.out.println("5. [bean属性赋值]:dog----依赖注入");
            this.animal = animal;
        }
    
    
        @Override
        public void setBeanName(String s) {
            System.out.println("6. 调用【BeanNameAware】--setBeanName:"+s);
    
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("7. 调用【BeanFactoryAware】--setBeanFactory");
        }
    
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
            System.out.println("8. 调用【ApplicationContextAware】--setApplicationContext");
    
        }
    
        /**
         * 初始化1
         */
        @PostConstruct
        public void myInit() {
            System.out.println("10. [初始化] 注解@PostConstruct自定义初始化方法[myInit]");
        }
    
        /**
         * 初始化2
         */
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("11. [初始化] 接口InitializingBean方法[afterPropertiesSet]");
    
        }
    
        /**
         * 初始化3
         */
        public void initMethod() {
            System.out.println("12. [初始化] 注解@Bean自定义初始化方法[initMethod]");
        }
    
        /**
         * 销毁1
         */
        @PreDestroy
        public void myDestroy() {
            System.out.println("14. [销毁] 注解@PreDestroy自定义销毁方法[myDestroy]");
        }
    
        /**
         * 销毁2
         */
        @Override
        public void destroy() throws Exception {
            System.out.println("15. [销毁] 接口DisposableBean方法[destroy]");
        }
    
        /**
         * 销毁3
         */
        public void destroyMethod() {
            System.out.println("16. [销毁] 注解@Bean自定义销毁方法[destroyMethod]");
        }
    }
    • 这里实现的接口只作用于当前bean(即是上面@bean定义的bean名为myDefineBeanName)生命周期

    后置处理器

    • 每个bean生命周期都执行一次
    • 后置处理器是作用于ioc容器中所有bean的生命周期。
    /**
     * @Description: todo
     * @Author: jianweil
     * @date: 2021/12/20 17:20
     */
    @Component
    public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
                System.out.println("============================InstantiationAwareBeanPostProcessor-开始======================");
                System.out.println("1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为"+beanName);
            }
            return null;
        }
    
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
                System.out.println("3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为"+beanName);
            }
            return true;
        }
    
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
                System.out.println("4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为"+beanName);
                System.out.println("============================InstantiationAwareBeanPostProcessor-结束======================");
    
            }
            return null;
        }
    }
    /**
     * @Description: 后置bean的初始化器:所有的bean都会拦截执行
     * @Author: jianweil
     * @date: 2021/12/8 9:46
     */
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            //这里过滤掉springboot自动配置的bean,只打印我们项目的bean情况
            if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
                System.out.println("9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为" + beanName);
            }
    
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
                System.out.println("13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为" + beanName);
            }
            return bean;
        }
    }

    工厂后置处理器

    • 容器级别,只允许一次
    @Component
    public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("0. [容器级别只调用一次] 调用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法");
        }
    }

    输出结果和结果解读

    • “//”标记为解读
    //容器级别的工厂后置处理器,只在应用上下文装配配置文件之后立即调用1次
    0. [容器级别只调用一次] 调用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法
    
    
    //因为我们生命过程只打印("myServiceBeanName".equals(beanName) || "dog".equals(beanName)),所有猫只有构造方法打印了
    猫----------构造方法
    
    //###############################dog的生命周期###############################################
    //后置处理器,容器级别,作用于所有bean
    ============================InstantiationAwareBeanPostProcessor-开始======================
    1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为dog
    //狗的实例化
    狗----------构造方法
    //后置处理器,容器级别,作用于所有bean
    3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为dog
    //后置处理器,容器级别,作用于所有bean
    4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为dog
    ============================InstantiationAwareBeanPostProcessor-结束======================
    //后置处理器,容器级别,作用于所有bean
    9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为dog
    //后置处理器,容器级别,作用于所有bean
    13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为dog
    //###############################dog的bean完成,开始myServiceBeanName###############################################
    
    
    //后置处理器,容器级别,作用于所有bean
    ============================InstantiationAwareBeanPostProcessor-开始======================
    1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为myServiceBeanName
    
    //实例化
    2. [bean实例化]:MyService----------构造方法
    
    //后置处理器,容器级别,作用于所有bean
    3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为myServiceBeanName
    //后置处理器,容器级别,作用于所有bean
    4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为myServiceBeanName
    ============================InstantiationAwareBeanPostProcessor-结束======================
    
    //属性赋值,即是依赖注入
    5. [bean属性赋值]:dog----依赖注入
    
    //bean级别,bean:myServiceBeanName实现了接口BeanNameAware
    6. 调用【BeanNameAware】--setBeanName:myServiceBeanName
    //bean级别
    7. 调用【BeanFactoryAware】--setBeanFactory
    //bean级别
    8. 调用【ApplicationContextAware】--setApplicationContext
    
    //后置处理器,容器级别,作用于所有bean:初始化前处理
    9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为myServiceBeanName
    
    //初始化
    10. [初始化] 注解@PostConstruct自定义初始化方法[myInit]
    11. [初始化] 接口InitializingBean方法[afterPropertiesSet]
    12. [初始化] 注解@Bean自定义初始化方法[initMethod]
    
    //后置处理器,容器级别,作用于所有bean:初始化后处理
    13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为myServiceBeanName
    
    //容器环境加载完成,这时可以使用所有bean
    2021-12-21 11:18:42.994  INFO 18956 --- [           main] c.l.s.SpringbootBeanLifecycleApplication : Started SpringbootBeanLifecycleApplication in 0.719 seconds (JVM running for 1.312)
    
    //销毁
    14. [销毁] 注解@PreDestroy自定义销毁方法[myDestroy]
    15. [销毁] 接口DisposableBean方法[destroy]
    16. [销毁] 注解@Bean自定义销毁方法[destroyMethod]
    
    Process finished with exit code 0

    Bean生命周期图

    了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。

    更多相关内容
  • 本篇文章主要介绍了详解Spring中bean生命周期回调方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 本篇文章主要介绍了浅谈Spring bean 生命周期验证,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Spring Bean生命周期在整个 Spring 中占有很重要的位置,掌握这些可以加深对 Spring 的理解。这篇文章主要介绍了Spring Bean 生命周期,需要的朋友可以参考下
  • 较完整的 bean生命周期

    千次阅读 2021-03-11 14:47:02
    首先需要说明的是,Bean生命周期主要指的是singleton bean,标签的scope默认就是singleton。对prototype bean来说,当用户getBean获得prototype bean的实例后,IOC容器就不再对当前实例进行管理,而是把管理权交由...

    首先需要说明的是,Bean的生命周期主要指的是singleton bean,标签scope默认就是singleton。对prototype bean来说,当用户getBean获得prototype bean的实例后,IOC容器就不再对当前实例进行管理,而是把管理权交由用户,此后再getBean生成的是新的实例。

     

    普通Java Bean和Spring Bean

    • 普通java对象就是new出来,然后不再使用的时候通过垃圾回收机制进行回收;
    • 而spring Bean是由spring容器来控制的,并且在创建的时候,赋予了一些特殊处理;

    有关 Java Bean, Spring Bean 和 Spring IoC 容器有一个很形象的比喻:小学生 (Java Bean)通过提交资料申请(元数据配置)加入了少先队(Spring Ioc 容器),学习了一些精神与规定之后,变成了少先队员(Spring Bean)。

    从这里可以看出,Java Bean 和 Spring Bean 都是具有特定功能的对象,小学生还是那个小学生,只不过加入了少先队之后有了新的身份,新的身份要按照组织 (Spring Ioc)的规定履行特定义务。

     

    bean的生命周期 经典四步

    由源码可知,最核心的逻辑就是四步:实例化 --> 填充属性  --> 初始化 --> 销毁

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    		if (instanceWrapper == null) {
    				//实例化
    				instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    		}
    
    		…………………………忽略其他代码
    
    		try {
    				//属性赋值
    				this.populateBean(beanName, mbd, instanceWrapper);
    				if (exposedObject != null) {
    						//初始化
    						exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    				}
    		} catch (Throwable var18) {
    				if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
    						throw (BeanCreationException)var18;
    				}
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
    		}
    
    		…………………………………………忽略其他代码
    
    		try {
    				//销毁
    				this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
    				return exposedObject;
    		} catch (BeanDefinitionValidationException var16) {
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
    		}
    }

    实例化

    实例化是bean生命周期中至关重要的一环,如何实例化呢?spring基于类,根据类的无参构造函数,反射得到一对象,这时候的对象,可以称为原始对象,因为最后得到bean,其实就是这个时候得对象,只不过是经过了一系列的处理。

    属性赋值

    对象实例化出来了,但是对象里边的属性,也得需要spring容器来自动赋值。

    比如AServiceImpl依赖了BService,那么这时候就用到@Autowired或@Resource注解,所以属性赋值的原理就是依赖注入,也就是这两个注解的原理。

    这两注解都可以用在属性和方法上,@Autowired是属于spring的,@Resource是数据java规范的;@Autowired是按byType注入,@Resource是默认按byName注入;

    上一副图看看这两注解的区别:

     

    初始化

    属性赋值完了就是初始化了,但是初始化该如何理解呢?就是我们在调用前,对象的某些属性有我们想要的值。以下是三种初始化方式:

              1. @PostConstruct

    public class UserService implements InitializingBean {
    
        @Autowired
        private OrderService orderService;
    
        //这种方式是 Spring 非常提倡的一种方式,我们通常将其标记在方法上即可,通常习惯将这个方法起名为 init()
        private final Map<String, String> map = new HashMap<>();
        @PostConstruct
        public void init(){
            this.map.put("支付", "1");
            this.map.put("部分支付", "2");
            this.map.put("未支付", "3");
        }
    }

            2、InitializingBean.afterPropertiesSet()

    public class UserService implements InitializingBean {
    
        @Autowired
        private OrderService orderService;
    
        //我们可以通过Spring 为我们提供的 InitializingBean 接口中的方法  afterPropertiesSet 内完成实例化的工作,
        //但是 Spring Framework 官方并不建议我们通过这种方法来完成 Bean 的实例化,这是一种强耦合的方式,我们看到框架层面才会用到这个方法。
        @Override
        public void afterPropertiesSet() throws Exception {
            this.map.put("支付", "1");
            this.map.put("部分支付", "2");
            this.map.put("未支付", "3");
        }
    }

           3、xml配置

            <bean id="myClass" class="com.demo.MyClass" init-method="init"/>

    以上就是三种初始化 Spring Beans 的方式,我们在框架中看到过三种方式在组合使用,那么组合使用的调用顺序是什么呢?

          1、首先@PostConstruct 会被最先调用

          2、其次 InitializingBean.afterPropertiesSet() 方法将会被调用

          3、最后调用通过 XML 配置的 init-method 方法或通过设置 @Bean 注解 设置 initMethod 属性的方法

    销毁

    • 销毁和初始化的方法一样,方法一:使用注解@PreDestroy;方法二:实现接口DisposableBean,重写destroy()方法;方法三:xml配置指定destroy-method="destroyMethod"
    • 容器销毁的时候,会销毁单例bean,但是容器什么时候销毁呢???

     

    实例化前的处理

    class --> BeanDefinition --> 推断构造方法 --> 实例化

    BeanDefinition

    bean的定义,spring扫描到类,将类的信息或者xml的信息保存到BeanDefinition结构,生成BeanDefinition;这个结构包括beanClass:bean的类型是什么、scope:bean的作用域、isLaze:),将类的属性放入一个map,后边有获取这个bean的时候,就可以通过这个map来获取bean的一些定义(比如scope就可以判断作用域,如果是单例的,直接获取,如果是原型,直接创建)

    推断构造方法

    后边的实例化需要根据构造函数来生成对象,如果类里边只有一个无参构造函数,那就一切soEasy了,,但是如果,有自定义的有参构造函数,那spring实例化的的时候就麻烦了,到底该使用哪个构造函数嘞。。所以就有了推断构造函数,先bytype后byname,选择可用的构造方法。

     

    初始化后的处理

    初始化 --> AOP --> userService代理对象 --> bean

    AOP:我们常说的aop就是在初始化之后,aop后得到的对象是一个代理对象。

    如何知道需要aop呢?spring会也会扫描所有的切面bean,拿到切面bean中的@Before等注解中的切点,和当前类,进行匹配,如果有匹配的切点,就进行aop,得到一个代理对象,最后bean就是代理对象。aop的实现是基于动态代理:参考博客

     

    初始化

    接下来就是重头戏初始化

    借用一张图,5、6是真实的初始化,在前边我们已经做过说明;3、4是在初始化之前;7是初始化之后;接下来我们就说说Aware和BeanPostProcessor。 

    我们先点进初始化代码initializeBean()瞅瞅

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    		// 3. 检查 Aware 相关接口并设置相关依赖
    		if (System.getSecurityManager() != null) {
    				AccessController.doPrivileged(new PrivilegedAction<Object>() {
    						public Object run() {
    								AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
    								return null;
    						}
    				}, this.getAccessControlContext());
    		} else {
    				this.invokeAwareMethods(beanName, bean);
    		}
    
     
    		// 4. BeanPostProcessor 前置处理
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
    				wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
    		}
    
    		// 5. 若实现 InitializingBean 接口,调用 afterPropertiesSet() 方法
    		// 6. 若配置自定义的 init-method方法,则执行
    		try {
    				this.invokeInitMethods(beanName, wrappedBean, mbd);
    		} catch (Throwable var6) {
    				throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
    		}
    
    		// 7. BeanPostProceesor 后置处理
    		if (mbd == null || !mbd.isSynthetic()) {
    				wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    
    		return wrappedBean;
    }

    Aware

    Aware类型的接口的作用就是让我们能够拿到Spring容器中的一些资源。基本都能够见名知意,Aware之前的名字就是可以拿到什么资源,例如BeanNameAware可以拿到BeanName,以此类推。调用时机需要注意:所有的Aware方法都是在初始化阶段之前调用的!

    若 Spring 检测到 bean 实现了 Aware 接口,则会为其注入相应的依赖。所以通过让bean 实现 Aware 接口,则能在 bean 中获得相应的 Spring 容器资源,类似这样:

    public class UserService implements InitializingBean, BeanNameAware, BeanClassLoaderAware {
    
        @Autowired
        private OrderService orderService;
    
    
        @Override
        public void afterPropertiesSet() throws Exception {
            this.map.put("支付", "1");
            this.map.put("部分支付", "2");
            this.map.put("未支付", "3");
        }
    
        @Override
        public void setBeanClassLoader(ClassLoader classLoader) {
            
        }
    
        @Override
        public void setBeanName(String name) {
    
        }
    }

    spring提供的Aware接口有很多:

    BeanFactory 类型的容器提供的aware接口:

    • BeanNameAware:注入当前 bean 对应 beanName;

    • BeanClassLoaderAware:注入加载当前 bean 的 ClassLoader;

    • BeanFactoryAware:注入 当前BeanFactory容器 的引用。

    ApplicationContext 类型的容器提供的aware接口:

    • EnvironmentAware:注入 Enviroment,一般用于获取配置属性;

    • EmbeddedValueResolverAware:注入 EmbeddedValueResolver(Spring EL解析器),一般用于参数解析;

    • ApplicationContextAware(ResourceLoader、ApplicationEventPublisherAware、MessageSourceAware):注入 ApplicationContext 容器本身。

    BeanPostProcessor

    BeanPostProcessor 接口,大家也应该有印象,里面只有两个方法:

    public interface BeanPostProcessor {
        Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;
    
        Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
    }

    看方法名,BeforeInitialization 和 AfterInitialization,我们应该猜得出,这是在上述三种方式的前和后,算是一种全局的切面思想,我们经常会使用 postProcessAfterInitialization 方法,通过读取 Bean 的注解完成一些后续逻辑编写与属性的设定。

    整合

    所以比较完整的生命周期应该是:

    扫描class --> BeanDefinition --> 推断构造方法 --> 实例化 --> 原始对象 --> 填充属性  --> Aware相关接口处理 --> BeanPostProcessor前置处理 --> 初始化 --> BeanPostProcessor后置处理 --> (AOP --> userService代理对象) --> bean

    先记住四个主要步骤,然后每个步骤在细化理解,这样就可以得到一个比较完整的bean的生命周期。有不完整或错误的地方,感谢各位指教。

    参考博客:参考一    参考二    参考三     参考四

    展开全文
  • 一般情况下,我们只是关心如何正确地将Bean装配到容器中,并不关心Ioc容器是如何装配和销毁Bean的过程。但是恰恰有时候,我们需要自定义初始化或销毁Bean的过程,以满足一些“特殊的”需求。比如,数据源在关闭的...
  • SpringBean生命周期详解

    千次阅读 多人点赞 2020-10-28 17:51:28
    SpringBean生命周期详解 一、简述: Spring是我们每天都在使用的框架,Bean是被Spring管理的Java对象,是Spring框架最重要的部分之一,那么让我们一起了解一下Spring中Bean的生命周期是怎样的吧 二、流程图 我们先从...

    SpringBean生命周期详解

    一、简述:

    Spring是我们每天都在使用的框架,Bean是被Spring管理的Java对象,是Spring框架最重要的部分之一,那么让我们一起了解一下Spring中Bean的生命周期是怎样的吧

    二、流程图

    在这里插入图片描述

    总体分为四个阶段:

      ①实例化 CreateBeanInstance
      ②属性赋值 PopulateBean
      ③初始化 Initialization
      ④销毁 Destruction**
    

    其中多个增强接口贯穿了这四个阶段!

    三、SpringBean生命周期中的增强接口PostProcessor:

    在上图里有多种后置处理器接口,它们贯穿了Bean的生命周期,且它们的实现类都会在SpringIOC容器进行初始化的时候进行实例化,让我们来做一个区分:

    |  |  ||--|--||  |  |

    解释:

    Bean的实例化:
    是指Spring通过反射获取Bean的构造方法进行实例化的过程
    Bean的初始化:
    是指Bean的属性赋值、执行初始化方法(init-method)的过程

    四、实例展示

    SpringBeanDemo

    package com.rx.spring;
     
    import com.rx.spring.domain.Person;
    import com.rx.spring.domain.Student;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
     
    public class SpringBeanDemo {
        public static void main(String[] args) throws Exception {
            System.out.println("****开始启动****");
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
            System.out.println("****启动完毕****");
            Person person = applicationContext.getBean("person", Person.class);
            Student student = applicationContext.getBean("student", Student.class);
     
            System.out.println("=============================================");
            System.out.println("person:" + person);
            System.out.println("student:" + student);
            person.destroy();
     
            System.out.println("============现在开始关闭容器======================");
            applicationContext.registerShutdownHook();
        }
    }
    

    Config

    package com.rx.spring;
     
    import org.springframework.context.annotation.*;
     
    @Configuration
    @ComponentScan("com.rx.spring")
    @ImportResource("classpath:spring.xml")
    public class Config {
         
    }
    

    Person

    package com.rx.spring.domain;
     
    import lombok.Data;
    import org.springframework.beans.factory.DisposableBean;
     
    @Data
    public class Person implements DisposableBean {
        private String name;
        private String address;
        private String tel;
     
        public Person(String name, String address, String tel) {
            System.out.println("Person--->>>有参构造方法");
            this.name = name;
            this.address = address;
            this.tel = tel;
        }
     
        public Person() {
            System.out.println("Person--->>>无参构造方法");
        }
     
        private void raoInitMethod() {
            System.out.println("person--->>>InitMethod...");
        }
     
        private void raoDestroyMethod() {
            System.out.println("person--->>>DestroyMethod...");
        }
     
        @Override
        public void destroy() throws Exception {
            System.out.println("【DisposableBean接口】调用DisposableBean.destroy()");
        }
    }
    

    Student

    package com.rx.spring.domain;
     
    import lombok.Data;
    import org.springframework.beans.factory.DisposableBean;
     
    @Data
    public class Student implements DisposableBean {
        private String username;
        private String password;
     
        public Student(String username, String password) {
            System.out.println("student--->>有参构造方法");
            this.username = username;
            this.password = password;
        }
        public Student() {
            System.out.println("student--->>>无参构造方法");
        }
     
        private void raoInitMethod() {
            System.out.println("student--->>>InitMethod...");
        }
     
        private void raoDestroyMethod() {
            System.out.println("student--->>>DestroyMethod...");
        }
     
        @Override
        public void destroy() throws Exception {
            System.out.println("【DisposableBean接口】调用DisposableBean.destroy()");
        }
    }
    

    RaoBeanFactoryPostProcessor

    package com.rx.spring.beanfactorypostprocessor;
     
    import org.springframework.beans.BeansException;
    import org.springframework.beans.MutablePropertyValues;
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.stereotype.Component;
     
    @Component
    public class RaoBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("postProcessBeanFactory...");
            String[] beanStr = beanFactory.getBeanDefinitionNames();
            for (String beanName : beanStr) {
                if ("person".equals(beanName)) {
                    BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
                    MutablePropertyValues m = beanDefinition.getPropertyValues();
                    if (m.contains("address")) {
                        //这个方法是判断是否有propertyName=username,有就替换,没有就添加
                        m.addPropertyValue("address", "大兴区");
                        System.out.println("***修改了address属性初始值了***");
                    }
                }
            }
        }
    }
    

    RaoInstantiationAwareBeanPostProcessor

    package com.rx.spring.beanpostprocessor;
     
    import com.rx.spring.domain.Person;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.PropertyValue;
    import org.springframework.beans.PropertyValues;
    import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
    import org.springframework.stereotype.Component;
     
    @Component
    public class RaoInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if ("person".equals(beanName) || "student".equals(beanName)) {
                System.out.println(beanName + "--->>>InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation....");
            }
            return null;
        }
     
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if ("person".equals(beanName) || "student".equals(beanName)) {
                System.out.println(beanName + "--->>>InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation....");
            }
            return bean instanceof Person;
        }
     
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            System.out.println(beanName + "--->>>InstantiationAwareBeanPostProcessor.postProcessProperties...");
            PropertyValue[] propertyValues = pvs.getPropertyValues();
            for (PropertyValue propertyValue : propertyValues) {
                if ("name".equals(propertyValue.getName())) {
                    propertyValue.setConvertedValue("改后rx");
                }
            }
            return pvs;
        }
    }
    

    RaoBeanPostProcessor

    
    package com.rx.spring.beanpostprocessor;
     
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
     
    @Component
    public class RaoBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if ("person".equals(beanName) || "student".equals(beanName)) {
                System.out.println(beanName + "--->>>BeanPostProcessor.postProcessBeforeInitialization...");
            }
            return bean;
        }
     
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if ("person".equals(beanName) || "student".equals(beanName)) {
                System.out.println(beanName + "--->>>BeanPostProcessor.postProcessAfterInitialization....");
            }
            return bean;
        }
    }
    

    spring.xml

    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
     
        <bean id ="person" class="com.rx.spring.domain.Person" init-method="raoInitMethod" destroy-method="raoDestroyMethod">
            <property name="name" value="rx"/>
            <property name="address" value="beijing"/>
            <property name="tel" value="157********"/>
        </bean>
     
        <bean id ="student" class="com.rx.spring.domain.Student" init-method="raoInitMethod" destroy-method="raoDestroyMethod">
            <property name="username" value="rx"/>
            <property name="password" value="1234"/>
        </bean>
     
    </beans>
    

    运行结果:

    在这里插入图片描述
    在这里插入图片描述

    运行结果符合预期,成功验证了之前的结论!!!

    原创不易,转载请附上本页面链接

    展开全文
  • Spring Bean是Spring应用中最最重要的部分了。下面这篇文章主要给大家介绍了关于Spring学习笔记之bean生命周期的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
  • Spring bean生命周期详解

    千次阅读 2021-09-10 10:49:21
    Spring bean生命周期 四个阶段 Bean的实例化阶段 Bean的设置属性阶段 Bean的 初始化阶段 Bean的销毁阶段 Spring bean生命周期13个环节 阶段1:Bean元信息配置阶段 阶段2:Bean元信息解析阶段 阶段3:将Bean注册到...

    Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点。
    在这里插入图片描述
    在这里插入图片描述

    Spring bean生命周期 四个阶段

    Bean的实例化阶段
    Bean的设置属性阶段
    Bean的 初始化阶段
    Bean的销毁阶段

    Spring bean生命周期13个环节

    阶段1:Bean元信息配置阶段
    阶段2:Bean元信息解析阶段
    阶段3:将Bean注册到容器中
    阶段4:BeanDefinition合并阶段
    阶段5:Bean Class加载阶段
    阶段6:Bean实例化阶段(2个小阶段)
    1.Bean实例化前阶段
    2.Bean实例化阶段
    阶段7:合并后的BeanDefinition处理
    阶段8:属性赋值阶段(3个小阶段)
    1.Bean实例化后阶段
    2.Bean属性赋值前阶段
    3.Bean属性赋值阶段
    阶段9:Bean初始化阶段(5个小阶段)
    1.Bean Aware接口回调阶段
    2.Bean初始化前阶段
    3.Bean初始化阶段
    4.Bean初始化后阶段
    5.Bean初始化完成
    阶段10:所有单例bean初始化完成后阶段
    阶段11:Bean的使用阶段
    阶段12:Bean销毁前阶段
    阶段13:Bean销毁阶段

    阶段1:Bean元信息配置阶段

    这个阶段主要是bean信息的定义阶段
    Bean信息定义4种方式

    1. API的方式
    2. Xml文件方式
    3. 注解的方式
      类上标注@Compontent注解来定义一个bean
      配置类中使用@Bean注解来定义bean
    4. properties文件的方式
      Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。

    不管是是通过xml配置文件的标签,还是通过注解配置的@Bean,还是@Compontent标注的类,还是扫描得到的类,它最终都会被解析成一个BeanDefinition对象,最后我们的Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作。

    你可以把BeanDefinition丢给Bean工厂或者其子类,然后Bean工厂就会根据这个信息帮你生产一个Bean实例
    一般用的是beanFactory的子类applicationcontext, applicationcontext比一般的beanFactory要多很多功能,比如aop、事件等。
    通过t加载配置文件,或者利用注解的方式扫描将bean的配置信息加载到spring容器里面。

    在这里插入图片描述

    BeanDefinition接口:bean定义信息接口
    AttributeAccessor接口:属性访问接口
    BeanMetadataElement接口:返回BeanDefinition定义的来源
    RootBeanDefinition类:表示根bean定义信息
    ChildBeanDefinition类:表示子bean定义信息
    GenericBeanDefinition类:通用的bean定义信息
    ConfigurationClassBeanDefinition类:表示通过配置类中@Bean方法定义bean信息
    AnnotatedBeanDefinition接口:表示通过注解的方式定义的bean信息
    BeanDefinitionBuilder:构建BeanDefinition的工具类,可以非常方便的组装BeanDefinition对象

    @Component 和 @Bean 的区别

    Spring帮助我们管理Bean分为两个部分,一个是注册Bean,一个装配Bean。
    完成这两个动作有三种方式,一种是使用自动配置的方式、一种是使用JavaConfig的方式,一种就是使用XML配置的方式。

    @Compent 作用就相当于 XML配置

    @Component
    public class Student {
    
        private String name = "lkm";
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    @Bean 需要在配置类中使用,即类上需要加上@Configuration注解

    @Configuration
    public class WebSocketConfig {
        @Bean
        public Student student(){
            return new Student();
        }
    
    }
    

    两者都可以通过@Autowired装配

    @Autowired Student student;

    那为什么有了@Compent,还需要@Bean呢?
    如果你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component注解的,因此就不能使用自动化装配的方案了,但是我们可以使用@Bean,当然也可以使用XML配置。

    阶段2:Bean元信息解析阶段

    Bean元信息的解析主要有3种方式

    1. xml文件定义bean的解析
      XML方式解析:XmlBeanDefinitionReader
    2. properties文件定义bean的解析
      properties文件定义bean的解析:PropertiesBeanDefinitionReader
    3. 注解方式定义bean的解析
      AnnotatedBeanDefinitionReader
      BeanDefinationReader的作用就是加载配置元信息,并将其转化为内存形式的BeanDefination

    阶段3:Spring Bean注册阶段

    bean注册阶段需要用到一个非常重要的接口:BeanDefinitionRegistry

    别名注册接口:AliasRegistry
    BeanDefinitionRegistry接口继承了AliasRegistry接口,这个接口中定义了操作bean别名的一些方法。

    BeanDefinitionRegistry唯一实现:DefaultListableBeanFactory
    org.springframework.beans.factory.support.DefaultListableBeanFactory
    例如 AnnotationConfigApplicationContext 类就实现了 BeanDefinitionRegistry接口

    Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。

    getBean这个方法的源码
    org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

    阶段4:BeanDefinition合并阶段

    org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition
    bean定义可能存在多级父子关系,合并的时候进进行递归合并,最终得到一个包含完整信息的RootBeanDefinition.

    合并之前是GenericBeanDefinition类型的,合并之后得到的是RootBeanDefinition类型的。

    后面的阶段将使用合并产生的RootBeanDefinition

    阶段5:Bean Class加载阶段

    这个阶段就是将bean的class名称转换为Class类型的对象。

    此时会对阶段4中合并产生的RootBeanDefinition中的beanClass进行解析,将bean的类名转换为Class对象,然后赋值给RootBeanDefinition#setBeanClassName字段

    上面得到了Bean Class对象以及合并之后的BeanDefinition,下面就开始进入实例化这个对象的阶段了。
    Bean实例化分为3个阶段:前阶段、实例化阶段、后阶段;

    阶段6:Bean实例化阶段

    Bean实例化前操作

    看一下 DefaultListableBeanFactory

    在 父类 AbstractBeanFactory 中
    private final List beanPostProcessors = new CopyOnWriteArrayList<>();
    是一个BeanPostProcessor类型的集合

    spring在bean生命周期的不同阶段,会调用上面这个列表中的BeanPostProcessor中的一些方法,来对生命周期进行扩展,bean生命周期中的所有扩展点都是依靠这个集合中的BeanPostProcessor来实现的

    Bean实例化之前会调用一段代码:
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation

    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    	for (BeanPostProcessor bp : getBeanPostProcessors()) {
    		if (bp instanceof InstantiationAwareBeanPostProcessor) {
    			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    			Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
    			if (result != null) {
    				return result;
    			}
    		}
    	}
    	return null;
    }
    

    上面代码中轮询beanPostProcessors列表,如果类型是InstantiationAwareBeanPostProcessor, 尝试调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation获取bean的实例对象,如果能够获取到,那么将返回值作为当前bean的实例,那么spring自带的实例化bean的过程就被跳过了.

    这个地方给开发者提供了一个扩展点,允许开发者在这个方法中直接返回bean的一个实例

    Bean实例化操作
    这个过程可以干什么?

    这个过程会通过反射来调用bean的构造器来创建bean的实例。
    org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
    这个方法会返回候选的构造器列表,也可以返回空.

    protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName)
    			throws BeansException {
    
    		if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
    					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
    					Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
    					if (ctors != null) {
    						return ctors;
    					}
    				}
    			}
    		}
    		return null;
    	}
    

    具体需要使用哪个构造器,spring为开发者提供了一个接口,允许开发者自己来判断用哪个构造器。
    重要的实现类 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
    可以将@Autowired标注的方法作为候选构造器返回
    到目前为止bean实例化阶段结束了

    阶段7:合并后的BeanDefinition处理

    这块的源码如下
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    	for (BeanPostProcessor bp : getBeanPostProcessors()) {
    		if (bp instanceof MergedBeanDefinitionPostProcessor) {
    			MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
    			bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    		}
    	}
    }
    

    会调用MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法

    第一个参数为beanDefinition,表示合并之后的RootBeanDefinition,我们可以在这个方法内部对合并之后的BeanDefinition进行再次处理

    实现类
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
    在 postProcessMergedBeanDefinition 方法中对 @Autowired、@Value 标注的方法、字段进行缓存

    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
    在 postProcessMergedBeanDefinition 方法中对 @Resource 标注的字段、@Resource 标注的方法、 @PostConstruct 标注的字段、 @PreDestroy标注的方法进行缓存

    阶段8:Bean属性设置阶段

    (1)调用 InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 方法,判断控制程序是否继续进行属性填充

    (2)根据注入类型(byType/byName),提取依赖的,统一存入 PropertyValues 中

    (3)判断是否需要进行 BeanPostProcessor 和 依赖检查:

    如果有后置处理器,将会应用 InstantiationAwareBeanPostProcessor 处理器的postProcessProperties 方法,对属性获取完毕填充前,对属性进行再次处理。 使用 checkDependencies方法来进行依赖检查
    (4)将所有解析到的 PropertyValues 中的属性填充至 BeanWrapper 中

    实例化后阶段
    会调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation这个方法,调用逻辑如下:
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    		throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    		result = beanProcessor.postProcessAfterInitialization(result, beanName);
    		if (result == null) {
    			return result;
    		}
    	}
    	return result;
    }
    

    postProcessAfterInstantiation方法返回false的时候,后续的Bean属性赋值前处理、Bean属性赋值都会被跳过

    Bean属性赋值前阶段
    这个阶段会调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法,调用逻辑
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

    if (hasInstAwareBpps || needsDepCheck) {
    	PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    	if (hasInstAwareBpps) {
    		for (BeanPostProcessor bp : getBeanPostProcessors()) {
    			if (bp instanceof InstantiationAwareBeanPostProcessor) {
    				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    				pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    				if (pvs == null) {
    					return;
    				}
    			}
    		}
    	}
    	if (needsDepCheck) {
    		checkDependencies(beanName, mbd, filteredPds, pvs);
    	}
    }
    

    如果InstantiationAwareBeanPostProcessor中的postProcessPropertyValues返回空的时候,表示这个bean不需要设置属性,直接返回了,直接进入下一个阶段
    PropertyValues 保存了bean实例对象中所有属性值的设置,所以我们可以在postProcessPropertyValues 这个方法中对PropertyValues值进行修改。

    这个方法有2个比较重要的实现类

    AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues在这个方法中对@Autowired、@Value标注的字段、方法注入值。
    CommonAnnotationBeanPostProcessor#postProcessPropertyValues在这个方法中对@Resource标注的字段和方法注入值。
    Bean属性赋值阶段
    这个过程比较简单了,循环处理PropertyValues中的属性值信息,通过反射调用set方法将属性的值设置到bean实例中。

    PropertyValues中的值是通过bean xml中property元素配置的,或者调用MutablePropertyValues中add方法设置的值。

    阶段9:Bean初始化阶段

    这个阶段分为5个小的阶段

    Bean Aware接口回调
    Bean初始化前操作
    Bean初始化操作
    Bean初始化后操作
    Bean初始化完成操作
    Bean Aware接口回调

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

    private void invokeAwareMethods(final String beanName, final Object bean) {
    		if (bean instanceof Aware) {
    			if (bean instanceof BeanNameAware) {
    				((BeanNameAware) bean).setBeanName(beanName);
    			}
    			if (bean instanceof BeanClassLoaderAware) {
    				((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    			}
    			if (bean instanceof BeanFactoryAware) {
    				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    			}
    		}
    	}
    

    如果我们的bean实例实现了上面的接口,会按照下面的顺序依次进行调用,

    BeanNameAware:将bean的名称注入进去
    BeanClassLoaderAware:将BeanClassLoader注入进去
    BeanFactoryAware:将BeanFactory注入进去

    Bean初始化前操作
    这个阶段的源码
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    		throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    		result = beanProcessor.postProcessBeforeInitialization(result, beanName);
    		if (result == null) {
    			return result;
    		}
    	}
    	return result;
    }
    

    会调用BeanPostProcessor的postProcessBeforeInitialization方法,若返回null,当前方法将结束。

    通常称postProcessBeforeInitialization这个方法为:bean初始化前操作。

    这个接口有2个实现类,比较重要:
    org.springframework.context.support.ApplicationContextAwareProcessor
    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

    ApplicationContextAwareProcessor注入6个Aware接口对象
    如果bean实现了下面的接口,在ApplicationContextAwareProcessor#postProcessBeforeInitialization中会依次调用下面接口中的方法,将Aware前缀对应的对象注入到bean实例中。
    EnvironmentAware:注入Environment对象 EmbeddedValueResolverAware:注入EmbeddedValueResolver对象 ResourceLoaderAware:注入ResourceLoader对象 ApplicationEventPublisherAware:注入ApplicationEventPublisher对象 MessageSourceAware:注入MessageSource对象 ApplicationContextAware:注入ApplicationContext对象

    CommonAnnotationBeanPostProcessor调用@PostConstruct标注的方法
    CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization中会调用bean中所有标注@PostConstruct注解的方法

    ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
    	@Override
    	public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
    		if (initAnnotationType != null) {
    			if (method.getAnnotation(initAnnotationType) != null) {
    				LifecycleElement element = new LifecycleElement(method);
    				currInitMethods.add(element);
    				if (debug) {
    					logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
    				}
    			}
    		}
    		if (destroyAnnotationType != null) {
    			if (method.getAnnotation(destroyAnnotationType) != null) {
    				currDestroyMethods.add(new LifecycleElement(method));
    				if (debug) {
    					logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
    				}
    			}
    		}
    	}
    })
    

    调用@PostConstruct标注的方法

    Bean初始化阶段
    2个步骤
    调用InitializingBean接口的afterPropertiesSet方法
    调用定义bean的时候指定的初始化方法。
    见:com.dn.spring.beandefinition.BeanDefinition5Test#test7

    Bean初始化后阶段
    这块的源码:
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

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

    调用BeanPostProcessor接口的postProcessAfterInitialization方法,返回null的时候,会中断上面的操作。
    通常称 postProcessAfterInitialization 这个方法为:bean初始化后置操作。

    阶段10:所有单例bean初始化完成后阶段

    所有单例bean实例化完成之后,spring会回调下面这个接口:

    public interface SmartInitializingSingleton {
        void afterSingletonsInstantiated();
    }
    

    调用逻辑在下面这个方法中
    //确保所有非lazy的单例都被实例化,同时考虑到FactoryBeans。 //如果需要,通常在工厂设置结束时调用。 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

    这个方法内部会先触发所有非延迟加载的单例bean初始化,然后从容器中找到类型是SmartInitializingSingleton的bean,调用他们的afterSingletonsInstantiated方法。

    阶段11:Bean使用阶段

    调用getBean方法得到了bean之后

    阶段12:Bean销毁阶段

    触发bean销毁的几种方式

    调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean
    调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
    调用ApplicationContext中的close方法
    Bean销毁阶段会依次执行

    轮询beanPostProcessors列表,如果是DestructionAwareBeanPostProcessor这种类型的,会调用其内部的postProcessBeforeDestruction方法
    如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法
    调用bean自定义的销毁方法
    DestructionAwareBeanPostProcessor接口

    public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
    
        /**
         * bean销毁前调用的方法
         */
        void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
    
        /**
         * 用来判断bean是否需要触发postProcessBeforeDestruction方法
         */
        default boolean requiresDestruction(Object bean) {
            return true;
        }
    }
    

    总结:

    BeanDefination(bean定义配置-解析-注册):

    配置元信息(bean定义配置)-BeanDefinationReader(解析)-BeanDefinationRegistry(注册);
    配置元信息(bean定义配置):API的方式,Xml文件方式,注解的方式,properties文件
    BeanDefinationRegistry:;键值对方式,通过特定的Bean定义的id,映射到相应的BeanDefination

    Bean实例化阶段:Bean实例化分为3个阶段:前阶段(容器启动,Bean Class加载BeanDefination)、实例化阶段、后阶段;

    BeanFactoryPostProcessor:是容器启动阶段Spring提供的一个扩展点,主要对注册的BeanDefination进行一定程度上的修改与替换。
    例如类名、scope、属性、构造函数参数列表、依赖的bean、是否是单例类、是否是懒加载等,
    容器的启动阶段的最终产物就是注册到BeanDefinationRegistry中的一个个BeanDefination了,这就是Spring为Bean实例化所做的预热的工作。

    spring bean实例化之后,就开始注入属性,
    首先注入自定义的属性,比如标注@autowrite的这些属性,
    再调用各种Aware接口扩展方法,注入属性(spring特有的属性),
    比如BeanNameAware.setBeanName,设置Bean的ID或者Name;

    在这里插入图片描述

    a.实例化Bean
    容器通过获取BeanDefinition对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。

    对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
    对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。

    实例化对象被包装在BeanWrapper对象中(可以认为是Bean的原生态),BeanWrapper提供了设置对象属性的接口,避免了使用反射机制设置属性。

    这里提到了4个组件:BeanFacotry\ApplicationContext\BeanDefinition\BeanWrapper

    b.设置对象属性(依赖注入)
    实例化后的对象被封装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。
    紧接着,Spring根据BeanDefinition中的信息进行依赖注入。
    并且通过BeanWrapper提供的设置属性的接口完成依赖注入。

    c.注入Aware接口(给bean增加某种能力,申明是某种特殊的bean)
    Aware接口用于增强Bean能力容器需检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean。
    常见的Aware接口有:BeanNameAware\BeanFactoryAware\ApplicationContextAware至此,一个对象已经被正确构造。

    d.1.BeanPostProcessor(自定义处理,满足用户需求)
    经过上述几个步骤后,bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现。 该接口提供了两个函数:

    postProcessBeforeInitialzation( Object bean, String beanName )
    当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会先于InitialzationBean执行,因此称为前置处理。所有Aware接口的注入就是在这一步完成的。

    postProcessAfterInitialzation( Object bean, String beanName )
    当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会在InitialzationBean完成后执行,因此称为后置处理。
    组件:BeanPostProcessor

    d.2.InitializingBean与init-method
    当BeanPostProcessor的前置处理完成后就会进入本阶段。 InitializingBean接口只有一个函数:afterPropertiesSet()这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。
    若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。
    当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口。

    e.DisposableBean和destroy-method
    和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑。

    关于Aware

    在设置属性阶段后,postProcessBeforeInitialization方法执行前,会执行很多Aware类型的接口,这种类型接口作用是加载资源到Spring容器中,Aware前面的名字就对应哪种资源,依次加载的是:

    BeanNameAware
    BeanClassLoaderAware
    BeanFactoryAware
    EnvironmentAware
    ResourceLoaderAware
    ApplicationEventPublisherAware
    ApplicationContextAware
    看到这里应该明白BeanFactory和ApplicationContext的区别了:
    BeanFactoryAware之前加载的资源都是公共的。BeanFactoryAware后面加载的资源都是ApplicationContext独有的。

    容器级扩展点(作用于所有bean):

    BeanFactoryPostProcessor接口:
    在循环初始化springbean之前,对BeanDefinition元数据做扩展处理
    InstantiationAwareBeanPostProcessor接口: 在对象实例化前后扩展,作用于所有bean
    BeanPostProcessor接口: 在对象初始化化前后扩展,作用于所有bean

    (2)、Bean扩展点(作用于单个bean):

    Aware接口: springBean实例化并且注入自定义属性之后 InitializingBean接口:
    springBean初始化时,执行构造方法结束,并且属性赋初始化值结束之后执行 DiposableBean接口:
    springBean销毁之前执行。

    (3)、Bean自身的方法

    包括了Bean本身调用的方法
    通过配置文件中的init-method和destroy-method指定的方法(或者用注解的方式)
    (4)、包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor,
    CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。
    工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

    展开全文
  • spring bean生命周期

    2019-01-16 08:37:23
    spring bean生命周期,把运行结果的日志,用sublime打开对比查看,你会有比较清晰的认识
  • Bean生命周期介绍

    2018-11-07 15:42:37
    Ben的创建初始化销毁的过程。 容器管理bean生命周期,我们还可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来自定义的初始化和销毁。
  • Bean生命周期概括起来有四个阶段: 实例化 -> 属性赋值 -> 初始化 -> 销毁 具体如下图所示: 1、实例化 实例化一个Bean,即new。 2、IOC依赖注入 按照Spring上下文对实例化的Bean进行配置。 - 3、...
  • Springbean生命周期详解

    2022-02-21 18:03:22
    在传统的java应用中,JavaBean的生命周期一般都是浅化理解,就是在在Java中使用关键字new把Bean进行实例化,然后Bean就可以使用了,一旦不使用了,Java会自动进行垃圾回收。 如果是在springBean里面,Bean生命...
  • Spring Bean 生命周期

    千次阅读 多人点赞 2020-09-24 14:02:10
    当容器销毁时,调用Bean的销毁方法 四、Bean 的生命周期验证 为了验证Bean生命周期的过程,有两种形式:一种是为面试而准备的,一种是为了解全过程而准备的,下面来看代码: Book.class public class Book ...
  • Bean生命周期 下图是标准的Bean生命周期 为了更好理解,可以重构成实例化、属性注入、初始化、销毁四个主要部分,其余部分相当于使用AOP技术,如果实现了相关接口,才会有这些过程。 从代码看Bean生命周期 ...
  • Spring Bean生命周期详解

    千次阅读 2020-04-18 23:06:58
    文章目录Spring bean生命周期13个环节阶段1:Bean元信息配置阶段阶段2:Bean元信息解析阶段阶段3:Spring Bean注册阶段 Spring bean生命周期13个环节 阶段1:Bean元信息配置阶段 阶段2:Bean元信息解析阶段 阶段3:...
  • 面试官问我SpringBean生命周期,我

    千次阅读 多人点赞 2021-08-23 16:08:43
    面试官:今天要不来聊聊Spring对Bean生命周期管理? 候选者:嗯,没问题的。 候选者:很早之前我就看过源码,但Spring源码的实现类都太长了 候选者:我也记不得很清楚某些实现类的名字,要不我大概来说下流程? ...
  • 主要给大家介绍了Spring中Bean生命周期和作用域及实现方式的相关资料,文中介绍的非常详细,对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
  • 且是bean生命周期中最先执行的方法; 返回非空:返回值是Object类型,这意味着我们可以返回任何类型的值,由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成对象的目标对象的实例,也就是说,...
  • bean生命周期流程图:Bean的生命周期流程 | ProcessOn免费在线作图,在线流程图,在线思维导图 | Bean的生成过程 1、生成BeanDefinition Spring启动的时候会进行扫描,会先调用org.springframework.context....
  • Bean生命周期(面试版)

    千次阅读 2021-11-09 19:06:28
    一、bean生命周期基本流程 实例化(通过反射创建对象) 属性填充(属性值非自动装配) 初始化(如数据源赋值、校验属性) 销毁(ioc容器销毁关闭,关闭数据源) 二、流程细节 1、初始化方法和销毁方法 public ...
  • 主要介绍了Spring bean生命周期配置过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • spring bean生命周期详解,源码分析

    千次阅读 2020-07-14 13:28:43
    目录如何获取beanClassPathXmlApplicationContext方法refresh源码分析finishBeanFactoryInitialization(beanFactory):spring bean的完整生命周期进阶版spring bean的完整生命周期 如何获取bean 首先,我们在代码中...
  • springBean生命周期

    万次阅读 多人点赞 2020-12-18 14:46:36
    一、springBean生命周期 1、 启动spring容器,也就是创建beanFactory(bean工厂), 一般用的是beanFactory的子类applicationcontext, applicationcontext比一般的beanFactory要多很多功能,比如aop、事件等。 通过...
  • 一.BeanDefinitionRegistryPostProcessor扩展点 1. 重写 postProcessBeanDefinitionRegistry BeanDefinitionRegistryPostProcessor ...2.获取BeanDefinitionRegistry,增删改BeanDefinition 能过实现 BeanDefinitionR
  • 一个对象转为Bean并由Spring IOC管理的过程如下,即一个Bean生命周期如下 如图所示: 如果简单来讲,笼统概括的话就四步: 1.实例化 2.设置属性值 3.初始化 4.销毁 但是详细来说,会有很多细节需要注意,...
  • 谈谈你对Spring Bean生命周期的理解【面试】

    万次阅读 多人点赞 2020-05-16 17:08:59
    前言 面试中经常会被问到Spring Bean生命周期,有些人说记不住,看了一遍源码也是云里雾里的,那是因为只看理论,没有自己实践,如果自己亲自写代码验证一下,不管是对Spring的宏观感受,还是微观的感觉,都会有...
  • 了解 Spring 容器管理的 Spring Bean 生命周期,包括对 Spring 容器和 IoC 的理解。 同时了解 Spring bean 生命周期回调处理程序和后处理器。 Spring Framework 提供了几种回调方法来创建 bean 和一些方法来销毁 ...
  • SpringBoot Bean生命周期

    2020-05-12 15:07:17
    首先上一张自制的自认为比较全的Spring Bean生命周期流程图: 测试代码: 测试bean @Data public class BeanLifeCycle implements InitializingBean, DisposableBean, BeanFactoryAware, BeanNameAware { ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 109,880
精华内容 43,952
关键字:

bean的生命周期

友情链接: GC_optimal.rar