【二三方】_SpringBoot项目启动时自动运行自定义方法

SpringBoot项目启动时自动运行自定义方法

在SpringBoot项目中有时候我们需要项目在启动时提前加载某些数据或执行某个方法,如:

  • 开启Quartz定时任务调度器;
  • 初始化sql,创建数据库。
方法一:实现ServletContextAware接口并重写其setServletContext方法,将其注入到Spring容器中
1
2
3
4
5
6
7
8
9
10
11
12
@Component
public class Starter1 implements ServletContextAware {
/**
* 在填充普通bean属性之后但在初始化之前调用
* 类似于initializingbean的afterpropertiesset或自定义init方法的回调
*/
@Override
public void setServletContext(ServletContext servletContext) {
//自定义方法
System.out.println("setServletContext方法");
}
}

使用该方法会在填充完普通Bean的属性,但是还没有进行Bean的初始化之前执行自定义方法。

方法二:实现ServletContextListener接口并重写其contextInitialized方法,将其注入到Spring容器中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component
public class Starter2 implements ServletContextListener {

/**
* 在初始化Web应用程序中的任何过滤器或servlet之前,将通知所有servletContextListener上下文初始化。
*/
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//ServletContext servletContext = sce.getServletContext();
System.out.println("执行contextInitialized方法");
}

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("执行contextDestroyed方法");
}
}
方法三:将要执行的方法所在的类交给Spring容器扫描(@Component),并且将要执行的方法放入静态代码块中
1
2
3
4
5
6
7
8
@Component
public class Starter3 {

//静态代码块会在依赖注入后自动执行,并优先执行
static {
System.out.println("注入Spring容器中的静态代码块");
}
}
方法四:将要执行的方法所在的类交给spring容器扫描(@Component),并且在要执行的方法上添加@PostConstruct注解
1
2
3
4
5
6
7
8
9
10
11
@Component
public class Starter4 {

/**
* Postcontruct注解在依赖注入完成后自动调用
*/
@PostConstruct
public static void haha(){
System.out.println("@Postcontruct在依赖注入完成后自动调用");
}
}
方法五:实现ApplicationRunner接口并重写其run方法,将其注入到Spring容器中
1
2
3
4
5
6
7
8
9
10
11
@Component
public class Starter5 implements ApplicationRunner {
/**
* 用于指示bean包含在SpringApplication中时应运行的接口。
* 在同一应用程序上下文中可以定义多个ApplicationRunner bean,可以使用有序接口或@order注释对其进行排序。
*/
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Starter5:ApplicationRunner的run方法");
}
}
方法六:实现CommandLineRunner接口并重写其run方法,将其注入到Spring容器中
1
2
3
4
5
6
7
8
9
10
11
12
@Component
public class Starter6 implements CommandLineRunner {
/**
* 用于指示bean包含在SpringApplication中时应运行的接口。
* 可以在同一应用程序上下文中定义多个CommandLineRunner bean,并且可以使用有序接口或@order注释对其进行排序。
* 如果需要访问ApplicationArguments而不是原始字符串数组,请考虑使用ApplicationRunner。
*/
@Override
public void run(String... strings) throws Exception {
System.out.println("Starter6:CommandLineRunner的run方法");
}
}
以上六种方法在SpringBoot项目启动时的执行顺序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2021-07-05 16:48:56.973 [main] [INFO] [org.apache.juli.logging.DirectJDKLog:180] - Starting Servlet Engine: Apache Tomcat/8.5.43 
2021-07-05 16:48:57.076 [localhost-startStop-1] [INFO] [org.apache.juli.logging.DirectJDKLog:180] - Initializing Spring embedded WebApplicationContext
2021-07-05 16:48:57.077 [localhost-startStop-1] [INFO] [org.springframework.boot.context.embedded.EmbeddedWebApplicationContext:271] - Root WebApplicationContext: initialization completed in 1364 ms
2021-07-05 16:48:57.210 [localhost-startStop-1] [INFO] [org.springframework.boot.web.servlet.ServletRegistrationBean:190] - Mapping servlet: 'dispatcherServlet' to [/]
2021-07-05 16:48:57.217 [localhost-startStop-1] [INFO] [org.springframework.boot.web.servlet.AbstractFilterRegistrationBean:251] - Mapping filter: 'characterEncodingFilter' to: [/*]
2021-07-05 16:48:57.219 [localhost-startStop-1] [INFO] [org.springframework.boot.web.servlet.AbstractFilterRegistrationBean:251] - Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2021-07-05 16:48:57.219 [localhost-startStop-1] [INFO] [org.springframework.boot.web.servlet.AbstractFilterRegistrationBean:251] - Mapping filter: 'httpPutFormContentFilter' to: [/*]
2021-07-05 16:48:57.219 [localhost-startStop-1] [INFO] [org.springframework.boot.web.servlet.AbstractFilterRegistrationBean:251] - Mapping filter: 'requestContextFilter' to: [/*]
Starter2:执行contextInitialized方法
Starter1:setServletContext方法
Starter3:注入Spring容器中的静态代码块
Starter4:@Postcontruct在依赖注入完成后自动调用
2021-07-05 16:53:47.708 [main] [INFO] [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter:557] - Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3b07a0d6: startup date [Mon Jul 05 16:48:55 CST 2021]; root of context hierarchy
2021-07-05 16:53:47.798 [main] [INFO] [org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry:544] - Mapped "{[/api/test/getAllData],methods=[POST || GET]}" onto public java.lang.String jingzhao.http.test.controller.HttpController.getAllData()
2021-07-05 16:53:47.803 [main] [INFO] [org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry:544] - Mapped "{[/schedule/open],methods=[GET]}" onto public java.lang.String jingzhao.quartz.test.controller.Switch.openSchedule()
2021-07-05 16:53:47.803 [main] [INFO] [org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry:544] - Mapped "{[/schedule/stop],methods=[GET]}" onto public java.lang.String jingzhao.quartz.test.controller.Switch.stopSchedule()
2021-07-05 16:53:47.807 [main] [INFO] [org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry:544] - Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2021-07-05 16:53:47.808 [main] [INFO] [org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry:544] - Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2021-07-05 16:53:47.845 [main] [INFO] [org.springframework.web.servlet.handler.AbstractUrlHandlerMapping:364] - Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2021-07-05 16:53:47.845 [main] [INFO] [org.springframework.web.servlet.handler.AbstractUrlHandlerMapping:364] - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2021-07-05 16:53:47.879 [main] [INFO] [org.springframework.web.servlet.handler.AbstractUrlHandlerMapping:364] - Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2021-07-05 16:53:48.051 [main] [INFO] [org.springframework.jmx.export.MBeanExporter:431] - Registering beans for JMX exposure on startup
2021-07-05 16:53:48.064 [main] [INFO] [org.apache.juli.logging.DirectJDKLog:180] - Starting ProtocolHandler ["http-nio-8448"]
2021-07-05 16:53:48.087 [main] [INFO] [org.apache.juli.logging.DirectJDKLog:180] - Using a shared selector for servlet write/read
2021-07-05 16:53:48.102 [main] [INFO] [org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer:210] - Tomcat started on port(s): 8448 (http)
Starter5:ApplicationRunner的run方法
Starter6:CommandLineRunner的run方法
2021-07-05 16:53:48.108 [main] [INFO] [org.springframework.boot.StartupInfoLogger:57] - Started Application in 307.879 seconds (JVM running for 314.096)