@PostConstruct和@PreDestroy与servlet生命周期的关系

执行顺序结果

/**
 * 服务器加载Servlet
 * ---> 创建servlet实例,实现servlet构造函数
 * ---> 执行注解@PostConstruct
 * ---> servlet.Init()
 * ---> servlet/service() 方法
 * ---> 执行注解@PreDestroy
 * ---> servlet.destroy()
 * ---> 服务器卸载Servlet完毕
 */

servlet生命周期

1.web服务器启动时,会对servlet进行实例化操作
2.第一次访问servlet时,会调用init方法进行初始化操作,这个操作只进行一次
3.每次访问servlet时,都会调用service方法进行真正的请求和响应
4.web服务器关闭时,会调用destroy进行销毁操作
5.在整个生命周期期间,init()和destroy()都各执行一次
6.与web服务器同生共死

 @PostConstruct和@PreDestroy与servlet生命周期的关系_第1张图片

Servlet的init()、destory()和Spring的PostConstruct、PreDestroy

Servlet 的 init() 和 destroy()

在 Servlet 的生命周期中,init() 和 destroy() 方法的作用分别是:

  1. init(): 此方法在 Servlet 实例化后立即调用,用于执行一次性的初始化工作(例如,打开数据库连接、初始化配置设置等)。Servlet 容器在部署后首次接收到对该 Servlet 的请求时,或者服务器启动时,会创建 Servlet 实例并调用其 init() 方法。

  2. destroy(): 此方法在 Servlet 的生命周期结束时调用,用于执行清理工作(例如,关闭数据库连接、释放资源等)。当服务器关闭,或者 Servlet 容器决定卸载 Servlet 时,会调用 destroy() 方法。

Spring 的 @PostConstruct 和 @PreDestroy

与 Servlet 的 init() 和 destroy() 类似,Spring 框架的 @PostConstruct 和 @PreDestroy 注解也用于执行一次性的初始化和清理工作,但是它们是基于 Java 的 JSR 250 标准,所以不仅限于 Spring:

  1. @PostConstruct: 此注解标记在一个方法上,表明该方法应在 bean 的所有必需依赖项已被 Spring 容器注入后调用,且在第一次对其他 bean 的使用之前。通常,此方法用于一次性的初始化工作。

  2. @PreDestroy: 此注解标记在一个方法上,表明该方法应在 bean 被容器销毁之前调用。通常,此方法用于执行清理工作。

即:@PostConstruct和@PreDestroy在整个服务运行过程中,有且只会被服务调用一次;

不同的是@PostConstruct是在服务启动的时候,一般用来init初始化配置与servlet中init()方法类似;而@PreDestroy是在服务结束的时候,一般用来清理资源,比如关闭线程池,与servlet中destory()方法类似;

 总的来说,无论是 Servlet 的 init() 和 destroy() 方法,还是 Spring 的 @PostConstruct 和 @PreDestroy 注解,它们的选择主要取决于你所处的环境以及你想要在何时执行初始化和清理工作。如果你在编写一个 Servlet,那么你可能需要使用 init() 和 destroy()。如果你在使用 Spring 框架,那么 @PostConstruct 和 @PreDestroy 就是好选择。

注意:在新版本JDK中, @PostConstruct和@PreDestroy并不在“javax.annotation.”包下面,而是在“jakarta.annotation.”包下面;

下面是测试案例

创建一个ServletDemo类

public class ServletDemo {
    public ServletDemo() {
        System.out.println("1.demo 构造器执行");
    }

    public void init() {
        System.out.println("3.demo init 方法执行");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("2.postConstruct 执行");
    }

    @PreDestroy
    public void preDestory() {
        // Disconnected from the target VM, address: '127.0.0.1:56517', transport: 'socket'
        System.out.println("5.preDestory 执行");
    }

    public void destory() {
        System.out.println("6.destory 开始执行...");
    }
}

创建一个ServletDemoConfig

public class ServletDemoConfig {
    @Bean(name = "servletDemo", initMethod = "init", destroyMethod = "destory")
    public ServletCat servletCat() {
        return new ServletDemo();
    }
}

Main启动类


public class ServletDemoMain {
    public static void main(String[] args) {
        startServletDemoConfig();
startServletDemo();
    }
 private static void startServletDemoConfig(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ServletDemoConfig.class);
        System.out.println("测试...Config");
        context.close();
    }
    private static void startServletDemo(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ServletDemo.class);
        System.out.println("测试...");
        context.close();
    }
}

最终结果

执行方法startServletDemoConfig时,相当于把@Configuration/@Component注解放在ServletDemoConfig类上面:

1.demo 构造器执行
2.postConstruct 执行
3.demo init 方法执行
测试...Config
5.preDestory 执行
6.destory 开始执行...

执行方法startServletDemo时,相当于把@Configuration/@Component注解放在ServletDemo类上面:

1.demo 构造器执行
2.postConstruct 执行
测试...
5.preDestory 执行

你可能感兴趣的:(servlet,spring,boot,spring,jdk)