Spring启动前后自动执行代码

有些Spring项目在启动的时候需要预加载一些资源,有以下方式:

 

一、启动前执行

   1、Java类加载阶段

    ①:static变量

      在类加载的准备阶段为static变量分配内存并设置类初始值(数据字段类型的默认值)

      在类加载的初始化阶段为static变量赋定义的值

    ②:static代码块

      在类加载的初始化阶段执行静态代码块

 

  2、监听器

    自定义监听器实现ApplicationListener接口,监听以下事件

容器开始启动 ApplicationStartingEvent

 

 

二、启动中执行

   1、bean实例化阶段

    ①:构造代码块

       每次创建对象时执行一次,优先于构造方法执行

    ②:构造方法

      每次创建对象时执行一次

 

  2、Spring bean初始化阶段

    ①:如果bean实现了BeanNameAware接口,Spring将调用setBeanName()方法将bean的ID传递入

    ②:如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入

    ③:如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传进来

 

    ④:@PostConstruct 标注的方法,在执行完构造器之后初始化对象时执行

    ⑤:afterPropertiesSet方法,若bean实现了InitializingBean接口,接着执行此初始化方法

    ⑥:initMethod,@Bean注解上自定义的初始化方法

 

  3、Spring监听器

    自定义监听器实现ApplicationListener接口,监听以下事件

在环境(environment)准备完成,容器创建之前 ApplicationEnvironmentPreparedEvent
容器创建完成,并且准备完成,资源加载之前 ApplicationContextInitializedEvent
容器加载完成,刷新之前 ApplicationPreparedEvent

 

 

三、启动后执行

  1、Spring监听器

    自定义监听器实现ApplicationListener接口,监听以下事件

 容器启动完成  ApplicationStartedEvent
 容器运行  ApplicationReadyEvent
 容器启动失败  ApplicationFailedEvent

  2、CommandLineRunner 和 ApplicationRunner

    两个接口都是在ApplicationStartedEvent事件之后执行 ,用于在Spring容器启动完成后执行一些功能。

    对应下图,callRunners方法:  

    

     先执行 ApplicationRunner 后执行 CommandLineRunner       

     

    两个接口都有一个run方法,区别在于run方法的入参不同

CommandLineRunner void run(String... args) throws Exception;
ApplicationRunner void run(ApplicationArguments args) throws Exception;

    ①:CommandLineRunner,接口,用于指示当一个bean被包含在一个SpringApplication中时应该运行它。可以在同一个应用程序上下文中定义多个CommandLineRunner bean,并且可以使用ordered接口或@Order注释进行排序

    ②:ApplicationRunner,接口,用于指示当一个bean被包含在一个SpringApplication中时应该运行它。可以在同一个应用程序上下文中定义多个ApplicationRunner bean,并且可以使用ordered接口或@Order注释进行排序

    

    使用:自定义类实现CommandLineRunner或ApplicationRunner接口,在实现的run()方法里执行想要自动执行的代码。

 

    Order注解:

      当有多个类实现了CommandLineRunner和ApplicationRunner接口时,可以通过在类上添加@Order注解来设定运行顺序。

 

    示例:

    SpringApplicationStartedListener:

import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * 监听当容器启动后,做一些数据预热工作
 */
@Component
public class SpringApplicationStartedListener implements ApplicationListener<ApplicationStartedEvent> {

    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        // 加载数据到缓存 ...
    }
}

    CacheRunner:

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * 容器启动后预热缓存
 */
@Component
public class CacheRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 预热缓存...
    }
}

 

 

END.

posted @ 2021-12-28 10:09  杨岂  阅读(1434)  评论(0编辑  收藏  举报