Spring注解驱动第八讲--容器中bean的生命周期

Posted xingjia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring注解驱动第八讲--容器中bean的生命周期相关的知识,希望对你有一定的参考价值。

bean的生命周期指的就是bean在容器中的:

  创建-->初始化-->销毁;

以上的过程都是由容器来进行管理.

我们可以自定义初始化和销毁方法,的那个进行到当前bean的生命周期的时候,调用我们自己定义的初始化方法和销毁方法.那么自定义初始化和销毁方法有以下四种方式:

1,指定初始化和销毁方法:

  在以往使用xml配置文件的时候可以在<bean>标签中加上"init-method"和"destory-method"属性来指定自定义的初始化和销毁方法,本文将不进行详细介绍;

2,使用@Bean注解的initMethod属性和destoryMethod属性来指定初始化方法和销毁方法

创建主配置类

@Configuration
public class MyconfigOfLifeCycle 
    @Bean(initMethod="init",destroyMethod="destory")//指定销毁和初始化方法,初始化方法是在创建对象之后执行,销毁方法是在容器关闭时执行
    public Mouse mouse() 
        return new Mouse() ;
    

创建Mouse的类

public class Mouse 
    public Mouse() 
        System.out.println("构造器创建Mouse...........");
    
    public void init() 
        System.out.println("初始化Mouse...........");
    
    public void destory() 
        System.out.println("销毁Mouse...........");
    

测试类:

public class IOCTest_lifeCycle 
    @Test
    public void test01()
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyconfigOfLifeCycle.class);
        System.out.println("容器创建完成.........");
        applicationContext.close();//关闭容器,关闭容器时,才会调用destory方法
    

运行结果:

七月 23, 2019 9:15:52 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@311d617d: startup date [Tue Jul 23 21:15:52 CST 2019]; root of context hierarchy
构造器创建Mouse...........
初始化Mouse...........
容器创建完成.........
七月 23, 2019 9:15:52 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@311d617d: startup date [Tue Jul 23 21:15:52 CST 2019]; root of context hierarchy
销毁Mouse...........

可以观察到,容器先去创建bean实体,然后进行初始化方法,当容器销毁时,对象也随之销毁.

注:在多实例的情况下,容器不会去创建bean,只有在调用时才会执行,创建方法和初始化方法,而关闭容器时容器也不会销毁对象实例.

2,将Bean的类实现InitializingBean和DisposableBean接口.

/**
 * InitializingBean接口中含有afterPropertiesSet方法,即在bean进行创建之后开始执行
 * DisposableBean接口中含有destroy方法,即在BeanFatory销毁的时候开始执行销毁方法
 *
 */
@Component//让容器可以扫描到
public class Cat implements InitializingBean,DisposableBean
    public Cat() 
        System.out.println("创建Cat............");
    
    public void destroy() throws Exception 
        System.out.println("初始化Cat............");
    
    public void afterPropertiesSet() throws Exception 
        System.out.println("销毁Cat............");
    

在主配置类中通过@ComponentScan注解扫描包下的bean

再一次执行测试类,运行结果如下:

创建Cat............
销毁Cat............
构造器创建Mouse...........
初始化Mouse...........
容器创建完成.........
七月 23, 2019 9:31:27 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@311d617d: startup date [Tue Jul 23 21:31:26 CST 2019]; root of context hierarchy
销毁Mouse...........
初始化Cat............

细心的读者可以发现,我竟然把吧打印的语句写反了^~^!!!!

3,可以使用JSR250提供的@PostConstruct在bean创建完成并属性值赋值完成后执行;@PreDestory在容器销毁bean之前执行.(两个注解都是加在方法上)

创建bean

@Component
public class Dog 
    
    public Dog() 
        System.out.println("Dog创建.......");
    
    @PostConstruct
    public void init() 
        System.out.println("Dog初始化.....@PostConstruct..");
    
    @PreDestroy
    public void destory() 
        System.out.println("Dog销毁.....@PreDestroy..");
    

运行结果:

创建Cat............
销毁Cat............
Dog创建.......
Dog初始化.....@PostConstruct..
构造器创建Mouse...........
初始化Mouse...........
容器创建完成.........
七月 23, 2019 9:58:30 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@311d617d: startup date [Tue Jul 23 21:58:30 CST 2019]; root of context hierarchy
销毁Mouse...........
Dog销毁.....@PreDestroy..
初始化Cat............

4,BeanPostProcessor:bean的后置处理器,在bean的初始化前后进行一些处理工作

首先创建自定义的类实现BeanPostProcessor接口

@Component
public class MyBeanPostProcessor implements BeanPostProcessor

    /**
     * 该方法在初始化之前执行
     * beanName:初始化当前bean对象的名字,
     * bean:初始化当前的bean对象
     * 
     * 返回的Object为初始化前在该方法中经过处理之后的对象(可原样返回)
     */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
        System.out.println("postProcessBeforeInitialization...." +beanName + "=>" + bean);
        return bean;
    
    /**
     * 该方法在初始化之后执行
     * beanName:初始化当前bean对象的名字,
     * bean:初始化当前的bean对象
     * 
     * 返回的Object为初始化之后在该方法中经过处理之后的对象(可原样返回)
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
        System.out.println("postProcessAfterInitialization...." +beanName + "=>" + bean);
        return bean;
    

之后在执行测试类,观察运行结果

创建Cat............
postProcessBeforeInitialization....cat=>com.wxj.bean.Cat@731f8236
初始化Cat............
postProcessAfterInitialization....cat=>com.wxj.bean.Cat@731f8236
Dog创建.......
postProcessBeforeInitialization....dog=>com.wxj.bean.Dog@4f9a3314
Dog初始化.....@PostConstruct..
postProcessAfterInitialization....dog=>com.wxj.bean.Dog@4f9a3314
构造器创建Mouse...........
postProcessBeforeInitialization....mouse=>com.wxj.bean.Mouse@75f9eccc
初始化Mouse...........
postProcessAfterInitialization....mouse=>com.wxj.bean.Mouse@75f9eccc
容器创建完成.........
七月 23, 2019 10:57:35 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@311d617d: startup date [Tue Jul 23 22:57:35 CST 2019]; root of context hierarchy
销毁Mouse...........
Dog销毁.....@PreDestroy..
销毁Cat............

通过观察结果可以看到,在每个bean初始化之前,都会先执行postProcessBeforeInitialization方法,而在初始化完成之后,会执行postProcessAfterInitialization方法.

注意:如果后置器处理中返回的为null,那么容器不会把使用@Bean注解的bean,加载到容器中

以上是关于Spring注解驱动第八讲--容器中bean的生命周期的主要内容,如果未能解决你的问题,请参考以下文章

Spring注解驱动开发在@Import注解中使用ImportBeanDefinitionRegistrar向容器中注册bean

Spring注解驱动开发使用InitializingBean和DisposableBean来管理bean的生命周期,你真的了解吗?

String注解驱动开发如何按照条件向Spring容器中注册bean?这次我懂了!!

Spring注解 - 生命周期属性赋值自动装配

Spring注解-生命周期与属性赋值

Spring注解驱动开发在@Import注解中使用ImportSelector接口导入bean