四、Srping之Bean的初始化和销毁

Srping之Bean的初始化和销毁方法

通常,bean的初始化和销毁方法我们有三个地方可以入手,分别是:

  • 自定义初始化,销毁方法
  • 实现spring提供的InitializingBean(初始化逻辑),DisposableBean(销毁逻辑)接口
  • JSR250;@PostConstruct,@PreDestroy执行初始化和销毁方法
  • 实现spring提供的BeanPostProcessor接口,实现其postProcessBeforeInitialization方法来执行在初始化之前的操作,实现postProcessAfterInitialization方法来执行初始化之后的操作。

bean的生命周期:实例化 -> 属性赋值 -> 初始化 -> 销毁

【1】自定义初始化,销毁方法

? 容器管理bean的生命周期:我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法

构造(对象创建):

  • 单实例:在容器启动的时候创建对象
  • 多实例:在每次获取的时候创建对象

销毁:

  • 单实例:容器关闭的时候
  • 多实例:容器不会管理这个bean;容器不会调用销毁方法,如果需要,自己手动调用销毁方法。

? 定义一个Person类,然后定义两个方法,一个是我们想作为初始化方法的init方法,一个是我们想作为销毁方法的destory方法

public class Person {
    public Person() {
        System.out.println("Person...constructor");
    }

    public void init(){
        System.out.println("Person...init");
    }

    public void destroy(){
        System.out.println("Person...destroy");
    }
}

? 将Person添加到配置类当中

@Configuration
public class LifeCycleConfig {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Person person(){
        return new Person();
    }
}

? 测试结果

public class LifeCycleConfigTest {
    @Test
    public void testLifeCycle(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
        System.out.println("容器创建完成了...");
        applicationContext.close();
    }
}
/**
Person...constructor
Person...init
容器创建完成了...
Person...destroy
*/

【2】InitializingBean和DisposableBean接口

? 我们还是在之前的Person类代码上继续编写

public class Person implements InitializingBean,DisposableBean{
    public Person() {
        System.out.println("Person...constructor");
    }

    public void init(){
        System.out.println("Person...init");
    }

    public void destry(){
        System.out.println("Person...destroy");
    }
    /**
     * 当beanFactory关闭且bean为单例的对象时触发
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean...Person.....destroy....");
    }

    /**
     * 当beanFactory实例化bean后,将所有的属性值设置完毕之后,才会调用该接口方法。
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean...Person.....afterPropertiesSet....");
    }
}

? 测试结果

/**
Person...constructor
InitializingBean...Person.....afterPropertiesSet....
Person...init
容器创建完成了...
DisposableBean...Person.....destroy....
Person...destroy
*/

可以看到,

  • 初始化过程:容器先调用了Person的无参构造方法来实例化Person对象实例,接着执行了InitialiaingBean的初始化方法afterPropertiesSet()方法,最后才执行我们自定义的init初始化方法。
  • 销毁过程:同样,容器也是先执行了DisposableBean的destroy方法,然后才执行了我们自定义的destry销毁方法。

【3】JSR250:@PostConstruct,@PreDestroy

  • @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法,
  • @PreDestroy:在容器销毁bean之前通知我们进行清理工作

? 继续在上面的Person代码上修改

public class Person implements InitializingBean,DisposableBean{
    public Person() {
        System.out.println("Person...constructor");
    }

    public void init(){
        System.out.println("Person...init");
    }

    public void destry(){
        System.out.println("Person...destroy");
    }

    @PostConstruct
    public void PostConstruct() {
        System.out.println("JSR250....PostConstruct....Person ... PostConstruct...");
    }

    @PreDestroy
    public void PreDestroy() {
        System.out.println("JSR250....PreDestroy....Person ... PreDestroy...");
    }

    /**
     * 当beanFactory关闭且bean为单例的对象时触发
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean...Person.....destroy....");
    }

    /**
     * 当beanFactory实例化bean后,将所有的属性值设置完毕之后,才会调用该接口方法。
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean...Person.....afterPropertiesSet....");
    }
}

? 测试结果:

/**
Person...constructor
JSR250....PostConstruct....Person ... PostConstruct...
InitializingBean...Person.....afterPropertiesSet....
Person...init
容器创建完成了...
JSR250....PreDestroy....Person ... PreDestroy...
DisposableBean...Person.....destroy....
Person...destroy
*/

可以看到:

  • 初始化方法的执行顺序:先执行Toyota的无参构造方法,再执行JSR250的PostConstruct初始化方法,接着执行InitializingBean的afterPropertiesSet初始化方法,最后执行我们自定义的init初始化方法。
  • 销毁方法的执行顺序:和初始化方法一样,先执行JSR250的PerDestroy销毁方法,再执行DisposableBean的destroy方法,最后执行我们自定义的destry销毁方法。

【4】实现BeanPostProcessor接口

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

  • postProcessBeforeInitialization:在初始化之前工作
  • postProcessAfterInitialization:在初始化之后工作

    直接观察代码,会发现BeanPostProcessor的方法postProcessBeforeInitialization有返回类型Object,

postProcessAfterInitialization也有返回类型Object,同时两个方法都可以抛出BeansException异常。

? 首先定义一个我们自己的BeanPostProcessor:

@Component
public class LifeCycleBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Person) {
            System.err.println("postProcessBeforeInitialization....拦截指定bean");
        }
        System.out.println("这句话证明所有容器中的bean都会被postProcessBeforeInitialization拦截.. beanName=" + beanName + "==>" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Person) {
            System.err.println("postProcessAfterInitialization.....拦截指定bean");
        }
        System.out.println("这句话证明所有容器中的bean都会被postProcessAfterInitialization拦截.. beanName=" + beanName + "==>" + bean);
        return bean;
    }
}

? 接着在配置类中添加注解包扫描:

@Configuration
@ComponentScan("com.zl")
public class LifeCycleConfig {

    @Bean(initMethod = "init",destroyMethod = "destry")
    public Person person(){
        return new Person();
    }
}

? 测试结果:

第一个标示点:说明所有容器加载的bean在实例化之后,初始化之前都会执行postProcessBeforeInitialization方法,在初始化完成后执行postProcessAfterInitialization方法。

第二个标示点:说明我们可以只拦截我们指定的bean,并且执行的顺序是:

  • 1.容器对bean进行实例化
  • 2.初始化前执行自定义BeanPostProcessor的postProcessBeforeInitialization方法
  • 3.如果存在JSR250的初始化方法,则执行其初始化方法
  • 4.如果实现了InitializingBean接口,则执行其afterPropertiesSet方法
  • 5.如果存在我们自定义的初始化方法(initMethod),则执行自定义初始化方法
  • 6.初始化方法结束后,执行自定义BeanPostProcessor的postProcessAfterInitialization方法。
  • 7.容器关闭时,若存在JSR250的销毁方法,则先调用JSR250的销毁方法
  • 8.若实现了DisposableBean接口,则调用其destroy方法
  • 9.最后,若存在我们自定义的销毁方法(destroyMethod),则执行我们自定义的销毁方法

以上九点,按顺序执行,完成bean的初始化和销毁工作。

需要注意的是,BeanPostProcessor提供的两个方法,是针对初始化前后的拦截操作,和容器的关闭,bean的销毁无关。

原文地址:https://www.cnblogs.com/lee0527/p/11748299.html

时间: 2024-11-09 03:56:32

四、Srping之Bean的初始化和销毁的相关文章

Spring中bean的作用域与bean的初始化与销毁

bean的作用域 通过在配置bean时,指定bean元素的scope来指定该bean的作用域 scope的默认值是singleton,即单例模式,在一个ApplicationContext中,每次调用getBean()方法,获取的都是同一个bean. 如果要使每次获取的bean 都不相同可以指定scope的值为prototype,那么每次调用getBean()都会获得一个新的bean Scope还可以去request指在一次Http请求中为单例 session在整个session范围中是单例的

spring bean的初始化和销毁

spring bean的初始化和销毁有3种形式: 1.通过注解@PostConstruct 和 @PreDestroy 方法实现初始化和销毁bean之前的操作. 2.通过xml配置init-method="" 和destory-method="" 3.通过实现InitializingBean和 DisposableBean接口

Spring Boot实战笔记(三)-- Spring常用配置(Bean的初始化和销毁、Profile)

一.Bean的初始化和销毁 在我们的实际开发的时候,经常会遇到Bean在使用之前或之后做些必要的操作,Spring对Bean的生命周期操作提供了支持.在使用Java配置和注解配置下提供如下两种方式: (1)Java配置的方式:使用 @Bean 的 initMethod 和 destroyMethod(相当于xml配置中的 init-method 和 destroy-method). (2)注解方式:利用JSR-250的 @PostContruct 和 @PreDestroy. 演示: 1.增加

Bean的初始化和销毁

在我们实际开发的时候,经常会遇到在Bean在使用之前或者之后做些必要的操作,Spring对Bean的生命周期的操作提供了支持.在使用Java配置和注解配置下提供如下两种方式.    1.Java配置方式:使用@Bean的initMethod和destroyMethod(相当于xml配置的init-method和destory-method).    2.注解方式:利用JSR-250的@PostConstruct和@PreDestroy. 实例 1.增加JSR250支持. <dependency>

Spring学习笔记--初始化和销毁Bean

可以使用bean的init-method和destroy-method属性来初始化和销毁bean.定义一个Hero类: package com.moonlit.myspring; public class Hero { public void born() { System.out.println("the hero is born."); } public void defaultBorn() { System.out.println("the hero is born b

spring实战装配bean之Bean的作用域以及初始化和销毁Bean

1.Bean的作用域 所有的spring bean默认都是单例.当容器分配一个Bean时,不论是通过装配还是调用容器的getBean()方法,它总是返回Bean的同一个实例.有时候需要每次请求时都获得唯一的Bean实例,那么就需要覆盖Spring默认的单例配置.当在Spring中配置<bean>元素时,可以为bean声明一个作用域.为了让spring在每次请求时都为bean产生一个新的实例,只需要配置bean的scope属性为prototype即可.如下所示: <bean id=&quo

Spring IOC - 控制反转(依赖注入) - 配置初始化和销毁的方法

在Spring中如果某个bean在初始化之后,或销毁之前要做一些额外操作可以为该bean配置初始化和销毁的我方法,在这些方法中完成需要的功能. 实验: 通过断点调试模式,测试初始化方法和销毁方法的执行 package cn.tedu.beans; public class ProdDao { public ProdDao() { System.out.println("ProdDao 被创建..."); } public void init() { System.out.println

spring-使用注解实现Bean初始化与销毁

一.创建项目    项目名称:spring100804二.在项目中添加spring 支持    1.在项目中创建lib目录        /lib    2.在lib目录下添加jar包        commons-logging.jar        junit-4.10.jar        log4j.jar        spring-beans-3.2.0.RELEASE.jar        spring-context-3.2.0.RELEASE.jar        spring

022 使用@Bean的属性完成初始化和销毁的指定

一 .概述 Bean的生命周期就是指,Bean的创建,初始化,销毁的整个过程. spring帮助我们实现整个过程,但是提供了很多的回调接口,我们 可以自己定义这些方法. 一共有四种方式可以实现这些. 二 . 使用 init-method 来实现. 组件: public class Person { public Person() { System.out.println("构造器在创建对象"); } public void init() { System.out.println(&qu