Spring核心——Bean的生命周期

导读:本篇文章讲解 Spring核心——Bean的生命周期,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

序言

Bean是Spring框架的核心,无论我们用的是SpringMVC、SpringBoot、SpringCloud都绕不开Bean的构造,理解了Bean的生命周期有利于我们更好的了解自己的项目并且可以对现有的框架做一些扩展。

一:Bean生命周期流程图

首先,看一下Bean整个生命周期的流程图,这张图有利于我们了解整个过程中的调用情况。
原图:https://www.processon.com/view/link/5e421d84e4b00de9fd84a623
Bean生命周期

二:测试方法以及步骤

Spring中有很多继承于Aware中的接口,aware的意思是已知的,所以从这些Aware中我们能从Spring容器获取到已知的一些信息。
简单举例来说,比如我们实现了ApplicationContextAware,我们就可以从里面获取到ApplicationContext上下文对象。

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext var1) throws BeansException;
}

下面通过简单的代码示例来模拟bean的生命周期。

1、创建一个bean

这个Bean实现了一下接口:

BeanFactoryAware
BeanNameAware
BeanClassLoaderAware
ResourceLoaderAware
MessageSourceAware
EnvironmentAware
ApplicationContextAware
InitializingBean
DisposableBean

Bean的实现如下:

public class UserInfo implements BeanFactoryAware,
        BeanNameAware,
        BeanClassLoaderAware,
        ResourceLoaderAware,
        MessageSourceAware,
        EnvironmentAware,
        ApplicationContextAware,
        InitializingBean,
        DisposableBean {
    //用户id
    Integer id;
    //用户名称
    String name;
    //用户性别
    String gender;
    //用户年龄
    String age;
    //备注
    String remarks;

    public UserInfo() {
        System.out.println(DateUtil.getTimeNow() + "调用UserInfo构造方法");
    }

    public void myInit() {
        System.out.println(DateUtil.getTimeNow() + "调用UserInfo的myInit()方法");
    }

    public void myDestroy() {
        System.out.println(DateUtil.getTimeNow() + "调用UserInfo的myDestroy()方法");
    }


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        System.out.println(DateUtil.getTimeNow() + "调用UserInfo赋值属性的setId()");
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println(DateUtil.getTimeNow() + "调用UserInfo赋值属性的setName()");
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        System.out.println(DateUtil.getTimeNow() + "调用UserInfo赋值属性的setAge()");
        this.age = age;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }

    @Override
    public String toString() {
        System.out.println(DateUtil.getTimeNow() + "调用UserInfo赋值属性的toString()");
        return DateUtil.getTimeNow() + "UserInfo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age='" + age + '\'' +
                ", remarks='" + remarks + '\'' +
                '}';
    }


    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println(DateUtil.getTimeNow() + "调用BeanClassLoaderAware的setBeanClassLoader()");
    }


    @Override
    public void setBeanName(String s) {
        System.out.println(DateUtil.getTimeNow() + "调用BeanNameAware的setBeanName()");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println(DateUtil.getTimeNow() + "调用ApplicationContextAware的setApplicationContext()");
        //模拟获取系统运行参数
        String sysProp = applicationContext.getEnvironment().getProperty("System.id");
        System.out.println(DateUtil.getTimeNow() + "获取系统参数System.id=" + sysProp);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println(DateUtil.getTimeNow() + "调用BeanFactoryAware的setBeanFactory()");
    }

    @Override
    public void setEnvironment(Environment environment) {
        System.out.println(DateUtil.getTimeNow() + "调用EnvironmentAware的setEnvironment()");
        System.out.println(DateUtil.getTimeNow() + environment.getProperty("user.dir"));

        //设置系统运行参数
        String sysProp = "springtest";
        System.out.println(DateUtil.getTimeNow() + "设置系统参数System.id=" + sysProp);
        System.setProperty("System.id", sysProp);

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(DateUtil.getTimeNow() + "调用InitializingBean的afterPropertiesSet()");

    }

    @Override
    public void setMessageSource(MessageSource messageSource) {
        System.out.println(DateUtil.getTimeNow() + "调用MessageSourceAware的setMessageSource()");
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        System.out.println(DateUtil.getTimeNow() + "调用BeanClassLoaderAware的setBeanClassLoader()");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(DateUtil.getTimeNow() + "调用DisposableBean赋值属性的destroy()");
    }
    
}
2、创建BeanFactoryPostProcessor 的实现实例
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println(DateUtil.getTimeNow() + "调用BeanFactoryPostProcessor构造方法");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println(DateUtil.getTimeNow() + "调用BeanFactoryPostProcessor的postProcessBeanFactor(),[" + configurableListableBeanFactory + "]");
    }
}
3、创建InstantiationAwareBeanPostProcessorAdapter实现实例

首先看一下UML图,了解一下跟BeanPostProcessor的关系:
UML图
然后接着去实例化InstantiationAwareBeanPostProcessorAdapter

public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

    public MyInstantiationAwareBeanPostProcessor(){
        super();
        System.out.println(DateUtil.getTimeNow() + "调用InstantiationAwareBeanPostProcessor构造方法");
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> aClass, String s) throws BeansException {
        System.out.println(DateUtil.getTimeNow() + "调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation(),[" + s + "]");
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object o, String s) throws BeansException {
        boolean resule = true;
        System.out.println(DateUtil.getTimeNow() + "调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(),[" + s + "], 返回: "+ resule);
        return resule;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues propertyValues, PropertyDescriptor[] propertyDescriptors, Object o, String s) throws BeansException {
        System.out.println(DateUtil.getTimeNow() + "调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues(),[" + s + "]");
        return propertyValues;
    }
}

4、创建BeanPostProcessor实现实例
public class MyBeanPostProcess implements BeanPostProcessor {

    public MyBeanPostProcess(){
        super();
        System.out.println(DateUtil.getTimeNow() + "调用BeanPostProcess构造方法");
    }

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println(DateUtil.getTimeNow() + "调用BeanPostProcess的postProcessBeforeInitialization(),[" + s + "]");
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println(DateUtil.getTimeNow() + "调用BeanPostProcess的postProcessAfterInitialization(),[" + s + "]");
        return o;
    }
}
5、将实例注册到Spring中

将以上几个实例注册到Spring中,然后进行测试

    <!-- 注入实例化的BeanFactoryPostProcessor-->
    <bean class="com.leo.model.MyBeanFactoryPostProcessor"></bean>
    <!-- 注入实例化的BeanPostProcessor -->
    <bean class="com.leo.model.MyBeanPostProcess"></bean>
    <!-- 注入实例化的InstantiationAwareBeanPostProcessor -->
    <bean class="com.leo.model.MyInstantiationAwareBeanPostProcessor"></bean>
    <!-- 手动定义一个bean -->
    <bean id="userInfo" name="userInfo2" class="com.leo.model.UserInfo" init-method="myInit" destroy-method="myDestroy">
        <property name="id" value="1"></property>
        <property name="name" value="张飒"></property>
        <property name="age" value="18"></property>
    </bean>

6、测试代码
    private static final String CLASS_PATH_RESOURCE = "applicationContext-test.xml";

    @Test
    public void classPathXmlApplicationContextTest() throws InterruptedException {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(CLASS_PATH_RESOURCE);
        UserInfo userInfo = (UserInfo) applicationContext.getBean("userInfo");
        System.out.println(userInfo);
        TimeUnit.SECONDS.sleep(3);//模拟业务运行
        applicationContext.registerShutdownHook();//销毁容器
    }
7、运行日志
[2020-02-24 11:11:35.596] 调用BeanFactoryPostProcessor构造方法
[2020-02-24 11:11:35.644] 调用BeanFactoryPostProcessor的postProcessBeanFactor(),[org.springframework.beans.factory.support.DefaultListableBeanFactory@4dfa3a9d: defining beans [com.leo.model.MyBeanFactoryPostProcessor#0,com.leo.model.MyBeanPostProcess#0,com.leo.model.MyInstantiationAwareBeanPostProcessor#0,userInfo]; root of factory hierarchy]
[2020-02-24 11:11:35.649] 调用BeanPostProcess构造方法
[2020-02-24 11:11:35.650] 调用InstantiationAwareBeanPostProcessor构造方法
[2020-02-24 11:11:35.671] 调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation(),[userInfo]
[2020-02-24 11:11:35.672] 调用UserInfo构造方法
[2020-02-24 11:11:35.672] 调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(),[userInfo], 返回: true
[2020-02-24 11:11:35.734] 调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues(),[userInfo]
[2020-02-24 11:11:35.773] 调用UserInfo赋值属性的setId()
[2020-02-24 11:11:35.774] 调用UserInfo赋值属性的setName()
[2020-02-24 11:11:35.774] 调用UserInfo赋值属性的setAge()
[2020-02-24 11:11:35.775] 调用BeanNameAware的setBeanName()
[2020-02-24 11:11:35.775] 调用BeanClassLoaderAware的setBeanClassLoader()
[2020-02-24 11:11:35.777] 调用BeanFactoryAware的setBeanFactory()
[2020-02-24 11:11:35.779] 调用EnvironmentAware的setEnvironment()
[2020-02-24 11:11:35.780] E:\WorkSpace\Git\spring-framework-learning-example\chapter-4-springmvc-sourcecode-analysis
[2020-02-24 11:11:35.780] 设置系统参数System.id=springtest
[2020-02-24 11:11:35.781] 调用BeanClassLoaderAware的setBeanClassLoader()
[2020-02-24 11:11:35.783] 调用MessageSourceAware的setMessageSource()
[2020-02-24 11:11:35.783] 调用ApplicationContextAware的setApplicationContext()
[2020-02-24 11:11:35.784] 获取系统参数System.id=springtest
[2020-02-24 11:11:35.785] 调用BeanPostProcess的postProcessBeforeInitialization(),[userInfo]
[2020-02-24 11:11:35.787] 调用InitializingBean的afterPropertiesSet()
[2020-02-24 11:11:35.788] 调用UserInfo的myInit()方法
[2020-02-24 11:11:35.789] 调用BeanPostProcess的postProcessAfterInitialization(),[userInfo]
[2020-02-24 11:11:35.818] 调用UserInfo赋值属性的toString()
[2020-02-24 11:11:35.819] UserInfo{id=1, name='张飒', gender='null', age='18', remarks='null'}
[2020-02-24 11:11:38.833] 调用DisposableBean赋值属性的destroy()
[2020-02-24 11:11:38.834] 调用UserInfo的myDestroy()方法

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/72737.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!