美文网首页J2EE学习--Spring
Spring bean的生命周期

Spring bean的生命周期

作者: 99793933e682 | 来源:发表于2017-04-19 00:29 被阅读237次

    什么是bean的生命周期?

    Spring是一个容器, bean是存在于容器中被管理的对象。bean的生命周期就是指bean从实例化到被设置属性,再到容器销毁时bean被销毁的整个过程。

    为什么要了解bean的生命周期?

    Spring 就是面向 Bean 的编程。如果把Spring比做一个舞台,那么bean就是舞台上的演员。Spring 作为Java中最优秀的框架之一,已被广泛的使用,很多第三方框架在设计的时候都考虑到了和Spring的集成,集成的根本其实就是在Spring容器中定义bean。而作为一个优秀的框架,Spring很多设计思想都独具匠心,在bean的整个生命周期过程中预留了很多扩展接口和自定义处理,掌握了bean的生命周期不仅可以学习优秀的设计模式,而且对理解 Spring 框架原理有非常好的作用,有助于深入理解Ioc和AOP。

    bean生命周期详解

    bean的生命周期不就是实例化,设置属性,使用完以后被销毁这么简单吗?实例化就是调用类的构造方法,设置属性就是调用setter方法注入,销毁甚至可以不用定义destroy方法。那么还有那么多要了解的么?

    日常开发中我们定义最多的就是下面这种业务bean,这类bean的生命周期的确很简单

    <bean id="xxService" class="com.xx.xx.service.impl.xxServiceImpl"/>
    

    除了这类bean的定义,我们在搭建Spring框架时其实还定义了很多bean。其中涉及到
    BeanNameAware, BeanFactoryAware, BeanFactoryPostProcessor,InitializingBean, DisposableBean等各种生命周期接口。例如

    属性加载器定义:

        <bean id="propertyConfigurer"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="ignoreUnresolvablePlaceholders" value="true"/>
            <property name="locations">
                <list>
                    <value>classpath:jdbc.properties</value>
                </list>
            </property>
        </bean>
    
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName">
                <value>${jdbc.driverClassName}</value>
            </property>
            ...
        </bean>
    

    线程池定义:

    <bean id ="asyncExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
            <property name="corePoolSize" value="20" />
            <property name="keepAliveSeconds" value="200" />
            <property name="maxPoolSize" value="300" />
            <property name="queueCapacity" value="300" />
            <property name="threadNamePrefix" value="test_asynchronousExecutor" />  
            <property name="threadGroupName" value="test_asynchronousExecutorGroup" />  
        </bean>
    
    下面我们详细介绍bean的生命周期过程
    1. 生命周期流程


      生命周期流程.png
    2. 各种生命周期接口方法分类

    Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

    1)Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法

    2)Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

    3)容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

    4)工厂后处理器接口方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在容器启动装配配置文件之后立即调用。 (PropertyPlaceholderConfigurer其实就是一个工厂后处理器接口的实现)

    3.代码演示

    1)定义一个bean,调用Bean自身的方法和Bean级生命周期接口方法。它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,同时有2个方法,对应配置文件中<bean>的init-method和destroy-method

    public class Person implements BeanFactoryAware, BeanNameAware,
            InitializingBean, DisposableBean {
    
        private String name;
        private String address;
        private int phone;
    
        private BeanFactory beanFactory;
        private String beanName;
    
        public Person() {
            System.out.println("【构造器】调用Person的构造器实例化");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            System.out.println("【注入属性】注入属性name");
            this.name = name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            System.out.println("【注入属性】注入属性address");
            this.address = address;
        }
    
        public int getPhone() {
            return phone;
        }
    
        public void setPhone(int phone) {
            System.out.println("【注入属性】注入属性phone");
            this.phone = phone;
        }
    
        @Override
        public String toString() {
            return "Person [address=" + address + ", name=" + name + ", phone="
                    + phone + "]";
        }
    
        // 这是BeanFactoryAware接口方法
        @Override
        public void setBeanFactory(BeanFactory arg0) throws BeansException {
            System.out
                    .println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
            this.beanFactory = arg0;
        }
    
        // 这是BeanNameAware接口方法
        @Override
        public void setBeanName(String arg0) {
            System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
            this.beanName = arg0;
        }
    
        // 这是InitializingBean接口方法
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out
                    .println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
        }
    
        // 这是DiposibleBean接口方法
        @Override
        public void destroy() throws Exception {
            System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
        }
    
        // 通过<bean>的init-method属性指定的初始化方法
        public void myInit() {
            System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
        }
    
        // 通过<bean>的destroy-method属性指定的初始化方法
        public void myDestory() {
            System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
        }
    }
    

    2)容器级生命周期接口BeanPostProcessor。BeanPostProcessor接口包括2个方法postProcessAfterInitialization和postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象

    public class MyBeanPostProcessor implements BeanPostProcessor {
    
        public MyBeanPostProcessor() {
            super();
            System.out.println("这是BeanPostProcessor实现类构造器!!");
        }
    
        @Override
        public Object postProcessAfterInitialization(Object arg0, String arg1)
                throws BeansException {
            System.out
            .println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");
            return arg0;
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object arg0, String arg1)
                throws BeansException {
            System.out
            .println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");
            return arg0;
        }
    }
    

    3)工厂后处理器接口方法

    public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
        public MyBeanFactoryPostProcessor() {
            super();
            System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
                throws BeansException {
            System.out
                    .println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
            BeanDefinition bd = arg0.getBeanDefinition("person");
            bd.getPropertyValues().addPropertyValue("phone", "110");
        }
    
    }
    

    4)配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
                http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    
        <bean id="beanPostProcessor" class="springBeanTest.MyBeanPostProcessor">
        </bean>
    
        <bean id="beanFactoryPostProcessor" class="springBeanTest.MyBeanFactoryPostProcessor">
        </bean>
        
        <bean id="person" class="springBeanTest.Person" init-method="myInit"
            destroy-method="myDestory" scope="singleton" p:name="张三" p:address="武汉"
            p:phone="15900000000" />
    
    </beans>
    

    5)测试代码

    public class BeanLifeCycle {
    
        public static void main(String[] args) {
    
            System.out.println("现在开始初始化容器");
            
            ApplicationContext factory = new ClassPathXmlApplicationContext("springBeanTest/beans.xml");
            System.out.println("容器初始化成功");    
            //得到Preson,并使用
            Person person = factory.getBean("person",Person.class);
            System.out.println(person);
            
            System.out.println("现在开始关闭容器!");
            ((ClassPathXmlApplicationContext)factory).registerShutdownHook();
        }
    }
    

    运行结果:

    现在开始初始化容器
    这是BeanFactoryPostProcessor实现类构造器!!
    BeanFactoryPostProcessor调用postProcessBeanFactory方法
    这是BeanPostProcessor实现类构造器!!
    【构造器】调用Person的构造器实例化
    【注入属性】注入属性address
    【注入属性】注入属性name
    【注入属性】注入属性phone
    【BeanNameAware接口】调用BeanNameAware.setBeanName()
    【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
    BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!
    【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
    【init-method】调用<bean>的init-method属性指定的初始化方法
    BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!
    容器初始化成功
    Person [address=武汉, name=张三, phone=110]
    现在开始关闭容器!
    【DiposibleBean接口】调用DiposibleBean.destory()
    【destroy-method】调用<bean>的destroy-method属性指定的初始化方法
    

    现在回过头来看看propertyConfigurer这个bean,它其实不是普通的bean,就是一个工厂后处理器,在容器启动的时候,它的postProcessBeanFactory方法被调用,方法逻辑就是从配置的locations路径中寻找properties文件,将文件内容转换为map对象,然后将容器中其他所有bean(其他是指非容器级生命周期接口的bean和非工厂后处理器的bean) <property>中的占位符替换成配置文件中的值。等到所有占位符替换完成,bean就可以正常的初始化了。

    说到bean的生命周期,不得不提一下FactoryBean接口,它和BeanFactory名字非常类似,但是含义却千差万别。 它是一个特殊的接口,实现了此接口的bean,容器将调用接口的getObject()方法得到该bean对象,而不是调用类的构造方法。除此之外,其他生命周期和前面描述的一样。

    FactoryBean实际应用:

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="xxx_master" />
            <property name="mapperLocations">
                <array>
                    <value>classpath*:mapper/**/*.xml</value>
                </array>
            </property>
        </bean>
    

    相关文章

      网友评论

        本文标题:Spring bean的生命周期

        本文链接:https://www.haomeiwen.com/subject/vkaqzttx.html