JAVA语言之深究Spring中Bean的生命周期
从安 2019-06-05 来源 : 阅读 773 评论 0

摘要:本篇文章主要讲述JAVA语言之深究Spring中Bean的生命周期,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。

本篇文章主要讲述JAVA语言之深究Spring中Bean的生命周期,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。

JAVA语言之深究Spring中Bean的生命周期

前言

 

网上大部分都是验证的Bean 在面试问的生命周期,其实查阅JDK还有一个完整的Bean生命周期,这同时也验证了书是具有片面性的,最fresh 的资料还是查阅原始JDK!!!

 

一、Bean 的完整生命周期

 

在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。

相比之下,Spring管理Bean的生命周期就复杂多了,正确理解Bean 的生命周期非常重要,因为Spring对Bean的管理可扩展性非常强,下面展示了一个Bean的构造过程

深究Spring中Bean的生命周期

 

Bean 的生命周期

Bean 的生命周期还是比较复杂的,下面来对上图每一个步骤做文字描述: 

1. Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化

2. Bean实例化后对将Bean的引入和值注入到Bean的属性中 

3. 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法 

4. 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入 

5. 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。 

6. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。 

7. 如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用 

8. 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。

9. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。

10. 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。 

上面是Spring 中Bean的核心接口和生命周期。

 

Bean 完整的生命周期 

文字解释如下: 

l BeanNameAware.setBeanName() 在创建此bean的bean工厂中设置bean的名称,在普通属性设置之后调用,在InitializinngBean.afterPropertiesSet()方法之前调用

 

l BeanClassLoaderAware.setBeanClassLoader(): 在普通属性设置之后,InitializingBean.afterPropertiesSet()之前调用

 

l BeanFactoryAware.setBeanFactory() : 回调提供了自己的bean实例工厂,在普通属性设置之后,在InitializingBean.afterPropertiesSet()或者自定义初始化方法之前调用

 

l EnvironmentAware.setEnvironment(): 设置environment在组件使用时调用

 

l EmbeddedValueResolverAware.setEmbeddedValueResolver(): 设置StringValueResolver 用来解决嵌入式的值域问题

 

l ResourceLoaderAware.setResourceLoader(): 在普通bean对象之后调用,在afterPropertiesSet 或者自定义的init-method 之前调用,在 ApplicationContextAware 之前调用。

 

l ApplicationEventPublisherAware.setApplicationEventPublisher(): 在普通bean属性之后调用,在初始化调用afterPropertiesSet 或者自定义初始化方法之前调用。在 ApplicationContextAware 之前调用。

 

l MessageSourceAware.setMessageSource(): 在普通bean属性之后调用,在初始化调用afterPropertiesSet 或者自定义初始化方法之前调用,在 ApplicationContextAware 之前调用。

 

l ApplicationContextAware.setApplicationContext(): 在普通Bean对象生成之后调用,在InitializingBean.afterPropertiesSet之前调用或者用户自定义初始化方法之前。在ResourceLoaderAware.setResourceLoader,ApplicationEventPublisherAware.setApplicationEventPublisher,MessageSourceAware之后调用。

 

l ServletContextAware.setServletContext(): 运行时设置ServletContext,在普通bean初始化后调用,在InitializingBean.afterPropertiesSet之前调用,在 ApplicationContextAware 之后调用注:是在WebApplicationContext 运行时

 

l BeanPostProcessor.postProcessBeforeInitialization() : 将此BeanPostProcessor 应用于给定的新bean实例 在任何bean初始化回调方法(像是InitializingBean.afterPropertiesSet或者自定义的初始化方法)之前调用。这个bean将要准备填充属性的值。返回的bean示例可能被普通对象包装,默认实现返回是一个bean。

 

l BeanPostProcessor.postProcessAfterInitialization() : 将此BeanPostProcessor 应用于给定的新bean实例 在任何bean初始化回调方法(像是InitializingBean.afterPropertiesSet或者自定义的初始化方法)之后调用。这个bean将要准备填充属性的值。返回的bean示例可能被普通对象包装

 

l InitializingBean.afterPropertiesSet(): 被BeanFactory在设置所有bean属性之后调用(并且满足BeanFactory 和 ApplicationContextAware)。

 

在BeanFactory 关闭的时候,Bean的生命周期会调用如下方法:

l DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(): 在销毁之前将此BeanPostProcessor 应用于给定的bean实例。能够调用自定义回调,像是DisposableBean 的销毁和自定义销毁方法,这个回调仅仅适用于工厂中的单例bean(包括内部bean)

 

l 实现了自定义的destory()方法

 

二、Bean 的生命周期验证

 

为了验证Bean生命周期的过程,有两种形式:一种是为面试而准备的,一种是为了解全过程而准备的,下面来看代码: 

Book.class 

public class Book implements BeanNameAware,BeanFactoryAware,
        ApplicationContextAware,InitializingBean,DisposableBean { 
    private String bookName;
    public Book(){
        System.out.println("Book Initializing ");
    } 
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Book.setBeanFactory invoke");
    } 
    public void setBeanName(String name) {
        System.out.println("Book.setBeanName invoke");
    } 
    public void destroy() throws Exception {
        System.out.println("Book.destory invoke");
    } 
    public void afterPropertiesSet() throws Exception {
        System.out.println("Book.afterPropertiesSet invoke");
    }
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Book.setApplicationContext invoke");
    } 
    public String getBookName() {
        return bookName;
    }
    public void setBookName(String bookName) {
        this.bookName = bookName;
        System.out.println("setBookName: Book name has set.");
    } 
    public void myPostConstruct(){
        System.out.println("Book.myPostConstruct invoke");
    } 
     // 自定义初始化方法
    @PostConstruct
    public void springPostConstruct(){
        System.out.println("@PostConstruct");
    } 
    public void myPreDestory(){
        System.out.println("Book.myPreDestory invoke");
        System.out.println("---------------destroy-----------------");
    }
    // 自定义销毁方法
    @PreDestroy
    public void springPreDestory(){
        System.out.println("@PreDestory");
    }
    @Override
    protected void finalize() throws Throwable {
        System.out.println("------inside finalize-----");
    }
}

自定义实现BeanPostProcessor 的MyBeanPostProcessor:

public class MyBeanPostProcessor implements BeanPostProcessor { 
    // 容器加载的时候会加载一些其他的bean,会调用初始化前和初始化后方法
    // 这次只关注book(bean)的生命周期
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Book){
            System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization");
        }
        return bean;
    } 
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Book){
            System.out.println("MyBeanPostProcessor.postProcessAfterInitialization");
        }
        return bean;
    }
}

在resources 目录下新建Bean-Lifecycle.xml

      
     
    
              
             
      
     

做一个启动类的测试,新建SpringBeanLifecycleApplication

public class SpringBeanLifecycleApplication {
 
    public static void main(String[] args) throws InterruptedException {
        // 为面试而准备的Bean生命周期加载过程
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
        Book book = (Book)context.getBean("book");
        System.out.println("Book name = " + book.getBookName());
        ((ClassPathXmlApplicationContext) context).destroy(); 
    } 
}

启动测试,输出结果如下:

Book Initializing
setBookName: Book name has set.
Book.setBeanName invoke
Book.setBeanFactory invoke
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
@PostConstruct
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
Book name = thingking in java 
@PreDestory
Book.destory invoke
Book.myPreDestory invoke

为了验证Bean完整的生命周期,需要新建一个SubBookClass 继承Book类

public class SubBookClass extends Book implements BeanClassLoaderAware,
        EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,
        ApplicationEventPublisherAware,MessageSourceAware{ 
    private String bookSystem; 
    public String getBookSystem() {
        return bookSystem;
    } 
    public void setBookSystem(String bookSystem) {
        System.out.println("设置BookSystem 的属性值");
        this.bookSystem = bookSystem;
    } 
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("SubBookClass.setBeanClassLoader() 方法被调用了");
    } 
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("SubBookClass.setApplicationEventPublisher() 方法被调用了");
    } 
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("SubBookClass.setEmbeddedValueResolver() 方法被调用了");
    } 
    public void setEnvironment(Environment environment) {
        System.out.println("SubBookClass.setEnvironment() 方法被调用了");
    } 
    public void setMessageSource(MessageSource messageSource) {
        System.out.println("SubBookClass.setMessageSource() 方法被调用了");
    } 
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println("SubBookClass.setResourceLoader() 方法被调用了");
    } 
}

上述SubBookClass类与Book是互补关系。 

新建一个SubBean-Lifecycle.xml,注入SubBookClass

 
                 
     

完整的SpringBeanLifecycleApplication 如下:

public class SpringBeanLifecycleApplication {
    public static void main(String[] args) throws InterruptedException {
        // 为面试而准备的Bean生命周期加载过程
        ApplicationContext context = new ClassPathXmlApplicationContext("Bean-Lifecycle.xml");
        Book book = (Book)context.getBean("book");
        System.out.println("Book name = " + book.getBookName());
        ((ClassPathXmlApplicationContext) context).destroy();
        // 完整的加载过程,当然了解的越多越好
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SubBean-Lifecycle.xml");
        SubBookClass subBookClass = (SubBookClass) applicationContext.getBean("bookClass");
        System.out.println("BookSystemName = " + subBookClass.getBookSystem());
        ((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();
    } 
}

输出完整的结果:

Book Initializing
setBookName: Book name has set.
Book.setBeanName invoke
Book.setBeanFactory invoke
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
@PostConstruct
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
Book name = thingking in java
@PreDestory
Book.destory invoke
Book.myPreDestory invoke
Book Initializing
设置BookSystem 的属性值
Book.setBeanName invoke
SubBookClass.setBeanClassLoader() 方法被调用了
Book.setBeanFactory invoke
SubBookClass.setEnvironment() 方法被调用了
SubBookClass.setEmbeddedValueResolver() 方法被调用了
SubBookClass.setResourceLoader() 方法被调用了
SubBookClass.setApplicationEventPublisher() 方法被调用了
SubBookClass.setMessageSource() 方法被调用了
Book.setApplicationContext invoke
MyBeanPostProcessor.postProcessBeforeInitialization
Book.afterPropertiesSet invoke
Book.myPostConstruct invoke
MyBeanPostProcessor.postProcessAfterInitialization
BookSystemName = Java System
Book.destory invoke
Book.myPreDestory invoke


本文由职坐标整理发布,学习更多的相关知识,请关注职坐标IT知识库!

本文由 @从安 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程