在开发过程中会有这样的场景:需要在容器启动的时候执行一些内容,如读取配置文件信息,清除缓存信息等。在Spring框架下是通过ApplicationListener监听器来实现的。这两个接口就是CommandLineRunner和ApplicationRunner,它们的执行时机是容器启动完成的时候。ApplicationRunner接口实现方法默认先于CommandLineRunner接口实现方法执行
1.实现CommandLineRunner接口
实现CommandLineRunner接口并重写run()方法,如果有多个CommandLineRunner的实现了可以使用@Order注解指定顺序。
package com.lx.startinit;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner=====Start");
System.out.println("hehe");
}
}
2.实现ApplicationRunner接口
实现ApplicationRunner接口并重写run方法,ApplicationRunner和CommandLineRunner的区别是在于参数的不同
package com.lx.startinit;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner=====Start");
System.out.println(args.getNonOptionArgs());
System.out.println(args.getOptionNames());
}
}
3.@PostConstruct注解
Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:
- 效果:在Bean初始化之后(构造方法和@Autowired之后)执行指定操作。
经常用在将构造方法中的动作延迟。
- 备注:Bean初始化时候的执行顺序:
构造方法 -> @Autowired -> @PostConstruct
@PreDestroy注解,准备销毁是发生
@PostConstruct
public void initComplete() {
System.out.println("PostConstruct=====Start");
}
4.实现InitializingBean接口
实现InitializingBean接口并重写 afterPropertiesSet()方法
package com.lx.startinit;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class MyInitializingBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean=====Start");
}
}
5.使用ContextRefreshedEvent事件(上下文件刷新事件)
ContextRefreshedEvent是Spring的ApplicationContextEvent一个实现,此事件会在Spring容器初始化完成后以及刷新时触发。
package com.lx.startinit;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class MyContextRefreshedEvent implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("ContextRefreshedEvent=====Start");
}
}
6.Springboot 初始化时ApplicationContextInitializer
ApplicationContextInitializer 接口用于在 Spring 容器刷新之前执行的一个回调函数,通常用于向 SpringBoot 容器中注入属性。
方式1: spring.factories 配置
新建一个类实现ApplicationContextInitializer接口
@Configuration
public class MyBootstrapAutoConfiguration implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("------jar包中-----MyBootstrapAutoConfiguration.initialize");
}
}
在 resources/META-INF/spring.factories 中配置,增加
# Initializers
org.springframework.context.ApplicationContextInitializer=\
com.lx.mybootstrapcommons.config.MyBootEnableAutoConfiguration
方式2: SpringApplication代码配置
新建一个类实现ApplicationContextInitializer接口
public class MyContextInitializerCode implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("------project包code方式中-----MyBootProjectConfiguration.initialize");
}
}
在main中增加
@SpringBootApplication
public class BootstrapCommonProgram {
public static void main(String[] args) {
SpringApplication springApplicationParam = new SpringApplication(BootstrapCommonProgram.class);
springApplicationParam.addInitializers(new MyContextInitializerCode());
ConfigurableApplicationContext configurableApplicationContext = springApplicationParam.run(args);
}
}
方式3:在application.ym配置
新建一个类实现ApplicationContextInitializer接口
public class MyContextInitializerProperties implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("------project包properties中-----MyBootProjectConfiguration.initialize");
}
}
在application.properties配置
context.initializer.classes=com.lx.bootstrapcommon.config.MyContextInitializerProperties
三种方式的优先级:
配置文件application.yml进行注入 > spring.factories进行注入 > 代码启动类进行注入
几种方式执行的默认的先后顺序
ApplicationContextInitializer > PostConstruct > InitializingBean > ContextRefreshedEvent > ApplicationRunner > CommandLineRunner
7 springboot 延迟初始化
SpringBoot在启动的时候可以选择开启是否延迟Bean的初始化,若开启了此项配置,则在SpringApplication启动期间,只会根据需要创建好必须的Bean,而不是一口气将所有的Bean都创建好。而那些尚未创建的Bean,只有当有需要的时候才会进行相应的创建。通常情况下,这样有利于减少SpringApplication的启动时间,特别是当项目越来越多Bean之后
7.1 方式一: 通过配置文件配置
spring.main.lazy-initialization=true
7.2 方式二: 通过main方式控制
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication();
// 开启延迟初始化
springApplication.setLazyInitialization(true);
// 启动SpringApplication
ConfigurableApplicationContext context = springApplication.run(LXbootWebProgram.class, args);
}
7.3 方式三: 通过开启@Indexed
引入依赖,并在启动类上增加@Indexed
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<optional>true</optional>
</dependency>
7.4 方式四: 关闭JMX
JMX的全称为Java Management Extensions. 顾名思义,是管理Java的一种扩展。这种机制可以方便的管理正在运行中的Java程序。常用于管理线程,内存,日志Level,服务重启,系统环境等。
spring.jmx.enabled=true