springboot如何在启动时执行指定方法
springboot如何在启动时执行指定方法
一、需求
有时候我们希望在springboot启动的时候执行一段代码完成一个特定任务,比如打印个springboot启动成功,又或者给其他项目发个通知说我启动完成啦。这个时候可以使用以下方法
- 实现CommandLineRunner接口
- 实现ApplicationRunner接口
- 实现ApplicationListener接口
- @PostConstruct
- 实现InitializingBean接口
下面我们在讲讲具体怎么使用上述方法!
二、实现CommandLineRunner接口
先上代码,如下即可。
1 |
|
实现CommandLineRunner接口 然后在run方法里面调用需要调用的方法即可,好处是方法执行时,项目已经初始化完毕,是可以正常提供服务的。
同时该方法也可以接受参数,可以根据项目启动时: java -jar demo.jar arg1 arg2 arg3 传入的参数进行一些处理。
三、实现ApplicationRunner接口
先上代码,如下即可。
1 |
|
实现ApplicationRunner接口和实现CommandLineRunner接口基本是一样的。
唯一的不同是启动时传参的格式,CommandLineRunner对于参数格式没有任何限制,ApplicationRunner接口参数格式必须是:–key=value
四、实现ApplicationListener接口
ApplicationListener的详细介绍可以看这里:
ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成ApplicationContext的事件机制。
如果容器中存在ApplicationListener的Bean,当ApplicationContext调用publishEvent方法时,对应的Bean会被触发。这一过程是典型的观察者模式的实现。
我们这里需要监听的是 ApplicationStartedEvent 事件,代码如下。
1 |
|
五、@PostConstruct
使用注解@PostConstruct是最常见的一种方式,存在的问题是如果执行的方法耗时过长,会导致项目在方法执行期间无法提供服务。
也就是说,在执行@postConstruct的时候,springboot并没有启动完成。还处在容器初始化阶段
1 |
|
六、实现InitializingBean接口
实现InitializingBean接口的方式和使用注解@PostConstruct的方式两者差球不多。
同样的在执行 InitializingBean 接口的方法时,springboot并没有启动完成。还处在容器初始化阶段
1 |
|
七、在启动方法中编写
这个不讲废话了。
1 |
|
八、六者的执行顺序与原理
执行顺序如下:
1 | PostConstruct - 1111 |
PostConstruct和InitializingBean是在容器初始化时调用。PostConstruct 在 InitializingBean 之前。
ApplicationListener《ApplicationStartedEvent》 监听的是 ApplicationStartedEvent 事件,该事件是在容器初始化完成,可以开始对外提供服务的时候调用。
ApplicationRunner和CommandLineRunner是在容器初始化完成,可以对外提供服务之后进行执行。他们之间可以使用Order注解或实现Ordered接口来指定执行顺序,值越小越先执行。
最后就是SpringApplication.run了。
九、注意事项
切勿在上述方法中编写会阻塞、死循环的代码,因为他们都是在主线程中运行。
这里说一个例子,在CommandLineRunner中写一个死循环,使用idea或者jar包启动的时候依然可以正常的对外提供服务,但是如果你使用外置tomcat部署,服务是不能正常访问的。因为tomcat会等所有的应用启动完成之后在开放服务访问,而CommandLineRunner导致springboot会一直处于启动中状态,tomcat从而无法对外提供服务。