Spring注解驱动开发(3)——bean的生命周期方法

目录

1. 关于bean的生命周期

bean的生命周期是指bean从创建到初始化到销毁的过程,bean的生命周期由IoC容器进行管理。Spring允许我们自定义bean的生命周期方法,并在bean的生命周期过程中进行回调。

2. bean的生命周期方法全解

2.1 通过@Bean指定initMethod和destroyMethod

创建一个Car类,并自定义初始化方法initMethod()和销毁方法destroyMethod()。

public class Car{

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

    //自定义初始化方法
    public void initMethod(){
        System.out.println("Car init........");
    }


    //自定义销毁方法
    public void destroyMethod(){
        System.out.println("Car destroy......");
    }
}

如何让Spring知道initMethod()是自定义的初始化方法,destroyMethod()是自定义的销毁方法?通过指定@Bean注解的initMethod属性和destroyMethod属性,值填方法名。

@Configuration
public class MainConfigOfLifeCycle {


    @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
    public Car car() {
        return new Car();
    }

}

测试代码如下

@Test
public void test1(){

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);

    System.out.println("容器启动完成.........");

    context.destroy();
}

运行得到测试结果如下

注意以上的例子是针对单实例bean而言(默认即为单实例),对于scope为prototype的bean,在第一次获取时才创建,且容器不会执行自定义的销毁方法。

2.2 实现InitializingBean或DisposableBean接口

InitializingBean也可以对bean进行自定义初始化,当bean的所有属性都已经注入完成后,该接口的方法会被Spring容器回调。

public interface InitializingBean {

   /**
    * Invoked by a BeanFactory after it has set all bean properties supplied
    * (and satisfied BeanFactoryAware and ApplicationContextAware).
    * <p>This method allows the bean instance to perform initialization only
    * possible when all bean properties have been set and to throw an
    * exception in the event of misconfiguration.
    * @throws Exception in the event of misconfiguration (such
    * as failure to set an essential property) or if initialization fails.
    */
   void afterPropertiesSet() throws Exception;

同理,DisposableBean接口允许用户自定义销毁逻辑

public interface DisposableBean {

   /**
    * Invoked by a BeanFactory on destruction of a singleton.
    * @throws Exception in case of shutdown errors.
    * Exceptions will get logged but not rethrown to allow
    * other beans to release their resources too.
    */
   void destroy() throws Exception;

}

创建一个Cat类,实现上述两个接口并重写相关抽象方法


public class Cat implements InitializingBean,DisposableBean {

    /**
     * 实现DisposableBean接口重写
     * @throws Exception
     */
    public void destroy() throws Exception {
        System.out.println("Cat DisposableBean destroy......");
    }

    /**
     * 实现InitializingBean接口重写
     * @throws Exception
     */
    public void afterPropertiesSet() throws Exception {

        System.out.println("Cat InitializingBean afterPropertiesSet.....");
    }
}

配置类和测试代码如下

@Configuration
public class MainConfigOfLifeCycle {


//    @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
//    public Car car() {
//        return new Car();
//    }

    @Bean
    public Cat cat(){
        return new Cat();
    }

}
@Test
public void test1(){

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);

    System.out.println("容器启动完成.........");

    context.destroy();
}

最后得到测试结果如下

2.3 使用@PostConstruct和@PreDestroy注解

这是JSR250中定义的两个注解。
@PostConstruct注解只能被使用在方法上,当bean的依赖已经注入完成并进行初始化前,被该注解标注的方法将被Spring容器回调。

* The PostConstruct annotation is used on a method that needs to be executed
* after dependency injection is done to perform any initialization
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

同样,@PreDestroy注解也只能被用在方法上,在bean被从容器中移除前,被该注解标注的方法将被Spring容器回调。

* The PreDestroy annotation is used on methods as a callback notification to
* signal that the instance is in the process of being removed by the
* container
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

自定义Dog类并在自定义方法上标注上这俩注解

public class Dog {


    @PostConstruct
    public void postConstruct(){
        System.out.println("Dog PostConstruct.....");
    }



    @PreDestroy
    public void preDestroy(){
        System.out.println("Dog PreDestroy....");
    }
}

最后测试结果如下

2.4 使用Bean的后置处理器接口BeanPostProcessor

这是容器级别的对bean的生命周期进行自定义的方式。ApplicationContext会自动注册实现了BeanPostProcessor接口的类,并将我们自定义的生命周期方法作用域每一个Bean的生命周期过程中。
BeanPostProcessor接口的定义如下,
该接口主要有两个抽象方法

public interface BeanPostProcessor {

   /**
    * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
    * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
    * or a custom init-method). The bean will already be populated with property values.
    * The returned bean instance may be a wrapper around the original.
    * @param bean the new bean instance
    * @param beanName the name of the bean
    * @return the bean instance to use, either the original or a wrapped one;
    * if {@code null}, no subsequent BeanPostProcessors will be invoked
    * @throws org.springframework.beans.BeansException in case of errors
    * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
    */
   Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

   /**
    * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
    * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
    * or a custom init-method). The bean will already be populated with property values.
    * The returned bean instance may be a wrapper around the original.
    * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
    * instance and the objects created by the FactoryBean (as of Spring 2.0). The
    * post-processor can decide whether to apply to either the FactoryBean or created
    * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
    * <p>This callback will also be invoked after a short-circuiting triggered by a
    * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
    * in contrast to all other BeanPostProcessor callbacks.
    * @param bean the new bean instance
    * @param beanName the name of the bean
    * @return the bean instance to use, either the original or a wrapped one;
    * if {@code null}, no subsequent BeanPostProcessors will be invoked
    * @throws org.springframework.beans.BeansException in case of errors
    * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
    * @see org.springframework.beans.factory.FactoryBean
    */
   Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
  • postProcessBeforeInitialization
    在bean初始化前(InitializingBean接口的afterPropertiesSet方法被调用前以及自定义的init-method方法被调用前)做些自定义的工作

  • postProcessAfterInitialization
    在bean完成初始化后(InitializingBean接口的afterPropertiesSet方法被调用后以及自定义的init-method方法被调用后)做些自定义工作

  • 创建Bean
public class Cat{

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

    public Dog() {

        System.out.println("Dog constructor.......");
    }
}
  • 配置类
@Configuration
public class MainConfigOfLifeCycle {


    @Bean
    public BeanPostProcessor postProcessor() {
        return new MyBeanPostProcessor();
    }

    @Bean
    public Dog dog() {
        return new Dog();
    }

    @Bean
    public Cat cat() {
        return new Cat();
    }

}
  • 测试代码
@Test
public void test1(){

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);

    System.out.println("容器启动完成.........");

    context.destroy();
}
  • 测试结果

可以看到,BeanPostProcessor提供了容器级别的,对所有bean都生效的生命周期增强手段。

3. 生命周期方法的执行顺序

  • Bean的类定义
public class Car implements InitializingBean,DisposableBean{

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

    //自定义初始化方法
    public void initMethod(){
        System.out.println("Car init........");
    }


    //自定义销毁方法
    public void destroyMethod(){
        System.out.println("Car destroy......");
    }

    //实现DisposableBean接口
    public void destroy() throws Exception {
        System.out.println("Car DisposableBean destroy......... ");
    }

    //实现InitializingBean接口
    public void afterPropertiesSet() throws Exception {

        System.out.println("Car InitializingBean afterPropertiesSet..... ");
    }


    @PostConstruct
    public void postConstructor(){
        System.out.println("Car postConstructor.......");
    }


    @PreDestroy
    public void preDestroy(){
        System.out.println("Car preDestroy....");
    }
}
  • 自定义BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        System.out.println(beanName+"=》"+"postProcessBeforeInitialization......");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName+"=》"+"postProcessAfterInitialization");
        return bean;
    }
}
  • 测试代码
@Test
public void test1(){

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);

    System.out.println("容器启动完成.........");

    context.destroy();
}
  • 运行结果

猜你喜欢

转载自www.cnblogs.com/rain-boy/p/9852037.html