一、概述

Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及销毁前执行特定的操作。被这两个注解修饰的方法可以保证在整个 Servlet 生命周期只被执行一次,即使 Web 容器在其内部中多次实例化该方法所在的 bean。

二、@PostConstruct 注解

@PostConstruct 该注解被用来修饰一个非静态的 void() 方法。被 @PostConstruct 修饰的方法会在服务器加载 Servlet 的时候运行,并且只会被服务器执行一次,并且在构造函数之后执行,init() 方法之前执行。

通常我们会是在 Spring 框架中使用到 @PostConstruct 注解,该注解的方法在整个 Bean 初始化中的执行顺序:Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)-> init()方法

如果想在生成对象时完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,为此,可以使用 @PostConstruct 注解的方法来完成初始化,@PostConstruct 注解的方法将会在依赖注入完成后被自动调用。

案例程序:

如果 userService 没有注入成功的话,@PostConstruct 注解的方法会报空指针异常 NullPointerException,加上 @PostConstruct 这个注解就是为了防止依赖注入没有完成。

MyUtils类: 

package com.example.quartzdemo.config;

import com.example.quartzdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

public class MyUtils {

    private static MyUtils staticInstance = new MyUtils();

    @Autowired
    private UserService userService;

    public MyUtils() {
        System.out.println("MyUtils类的构造方法...");
    }

    public void init() {
        System.out.println("MyUtils类的init()方法...");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("MyUtils类的postConstruct方法...");
        staticInstance.userService = userService;
    }

    public static void invokeBean(){
        staticInstance.userService.getName();
    }

}

 接下来在config里使用 @Bean 注解将 MyUtils类注册到 Spring 容器中,如下所示:

// initMethod指向Cat里的init()方法
    @Bean(initMethod = "init")
    public MyUtils myUtils() {
        return new MyUtils();
    }

运行结果: 

三、@PreDestroy 注解

@PreDestroy 该注解被用来修饰一个非静态的 void() 方法。被 @PreDestroy 修饰的方法会在服务器卸载 Servlet 的时候运行,并且只会被服务器执行一次。

执行顺序:构造方法 -> @PostConstruct -> init()方法 -> @PreDestroy -> destroy() 方法 -> bean 销毁

案例程序:

Cat类:

package com.example.quartzdemo.config;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class Cat {

    public Cat() {
        System.out.println("Cat类的构造方法。。。");
    }
    
    public void init() {
        System.out.println("Cat的init()方法。。。");
    }
    
    @PostConstruct
    public void postConstruct() {
        System.out.println("Cat的postConstruct()方法。。。");
    }
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("Cat的preDestroy()方法。。。");
    }
    
    public void destroy() {
        System.out.println("Cat的destroy() 方法。。。");
    }
    
}

可以看到,在 Cat 类中,我们提供了构造方法,init() 方法、destroy() 方法,使用 @PostConstruct 注解标注的 postConstruct() 方法和只用 @PreDestroy 注解标注的 preDestroy() 方法。接下来在config里使用 @Bean 注解将 Cat 类注册到 Spring 容器中,如下所示:

 destroyMethod = "destroy":当该 bean 为单例模式,才能调用该方法,destroy 方法在容器销毁的时候被调用。当该 bean 为多例时,spring 容器不负责容器的销毁工作,当不用该 bean 时应该手动的进行销毁。

    // initMethod指向Cat里的init()方法,destroyMethod指向Cat里的destroy()方法
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Cat cat() {
        return new Cat();
    }

在启动类上进行测试,如下所示:

public class QuartzDemoApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(QuartzDemoApplication.class, args);
        context.close();
    }

}

运行结果:

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐