1. 程式人生 > >Spring 中容器初始化時呼叫的介面類

Spring 中容器初始化時呼叫的介面類

  在日常開發中難免會經常遇到這樣的應用場景,在專案初始化時執行指定的程式碼實現一些功能,或者在專案啟動後執行一些程式碼實現功能。這個時候就需要用到Spring提供的一些介面、註解了。本文都是以SpringBoot為基礎。

1.Spring容器啟動前執行

   1.1介面類InitializingBean

         直接在程式碼中實現該介面afterPropertiesSet方法,並在該方法中執行程式碼。

         值得注意的是  在該介面執行時Spring 容器是還沒有初始化完成的。在這裡取spring容器中的物件可能會被丟擲空指標異常。

@Component
public class TestConfigInitializingBean implements InitializingBean {
	private static final Logger LOGGER = LoggerFactory.getLogger(TestConfigInitializingBean.class);

	@Override
	public void afterPropertiesSet() throws Exception {
		LOGGER.info("--------------------------------------------");
		LOGGER.info("-----正在執行InitializingBean實現類程式碼-----");
		LOGGER.info("--------------------------------------------");
	}

}

     1.2 註解實現@PostConstruct

        這種方式相對於InitializingBean介面實現要方便一些。直接在需要的方法上新增該註解即可。

        這種方式與上面InitializingBean介面一樣都是在spring容器初始化前執行,所有在該註解方法中獲取容器內物件可能存在空指標異常


@Component
public class TestPostConstruct {

	private static final Logger LOGGER = LoggerFactory.getLogger(TestPostConstruct.class);

	@PostConstruct
	public void initPostConstruct() {
		LOGGER.info("--------------------------------------------");
		LOGGER.info("-----正在執行@PostConstruct實現類程式碼-----");
		LOGGER.info("--------------------------------------------");
	}

}

2 Spring容器初始化完成後執行

  2.1 實現監聽器 ApplicationListener<ApplicationEvent>

      關於這個介面,很多人可能會遇到多次執行該方法。其實這是正常現象,我在執行這段程式碼時,被重複呼叫了3次

     通過debug除錯觀察發現,3次執行引數ApplicationEvent event都是不同的。

     第一次引數內source是AnnotationConfigEmbeddedWebApplicationContext

     第二次引數內source是TomcatEmbeddedServletContainer

     第三次引數內source是SpringApplication

    我個人的理解為springboot web容器載入時觸發該方法一次,springboot自帶tomcat容器初始化時觸發容器一次

     第三次是springApplication  建立並初始化Spring上下文時再次觸發該監聽

      直接上程式碼

@Component
public class TestConfigApplicationListener implements ApplicationListener<ApplicationEvent> {
	private static final Logger LOGGER = LoggerFactory.getLogger(TestConfigApplicationListener.class);

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		LOGGER.info("--------------------------------------------");
		LOGGER.info("-----正在執行ApplicationListener實現類程式碼-----");
		LOGGER.info("--------------------------------------------");
	}

}

    補充: ApplicationEvent該類是一個監聽事件抽象類,它下面有很多子類。分別實現不同的事件監聽。該監聽器的具體執行時間可根據不同的監聽型別物件(ApplicationEvent子類)在不同的時間執行 專案啟動前、啟動後等,具體每個類的監聽後面的文章在分析。

    原理:ApplicationContextAware介面提供了publishEvent方法,實現了Observe(觀察者)設計模式的傳播機制,實現了對bean的傳播。通過ApplicationContextAware把系統中所有ApplicationEvent傳播給所有的ApplicationListener。

      2.2 實現介面ApplicationRunner

        在程式碼中實現介面的run方法,並在run方法中編寫邏輯程式碼

       該方法可以通過@order(value= 數字) 來控制執行順序,順序是依次從小到大執行

@Component
@Order(value = 3)
public class TestConfigApplicationRunner implements ApplicationRunner {
	private static final Logger LOGGER = LoggerFactory.getLogger(TestConfigApplicationRunner.class);

	@Override
	public void run(ApplicationArguments args) throws Exception {
		LOGGER.info("--------------------------------------------");
		LOGGER.info("-----正在執行ApplicationRunner實現類程式碼-----");
		LOGGER.info("--------------------------------------------");
	}

}

       2.2 實現介面CommandLineRunner

        CommandLineRunner介面的使用方式與ApplicationRunner介面基本相似,不同的只是方法的引數型別,CommandLineRunner的引數是基本型別,而ApplicationRunner是的引數是ApplicationArguments物件,經過封裝,使用者可對引數進行更多操作

@Component
@Order(value = 2)
public class TestConfigCommandLineRunner implements CommandLineRunner {

	private static final Logger LOGGER = LoggerFactory.getLogger(TestConfigCommandLineRunner.class);

	@Override
	public void run(String... args) throws Exception {
		LOGGER.info("--------------------------------------------");
		LOGGER.info("-----正在執行CommandLineRunner實現類程式碼-----");
		LOGGER.info("--------------------------------------------");
	}

}

程式碼最終執行結果日誌:


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::       (v1.5.10.RELEASE)

2018-09-05 12:20:08.212  INFO 7140 --- [           main] com.port.test.PortTestApp                : Starting PortTestApp on DESKTOP-R7GPPNQ with PID 7140 (E:\workSpace\learn-project\port-test\target\classes started by zane in E:\workSpace\learn-project\port-test)
2018-09-05 12:20:08.214  INFO 7140 --- [           main] com.port.test.PortTestApp                : No active profile set, falling back to default profiles: default
2018-09-05 12:20:08.255  INFO 7140 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot[email protected]140e5a13: startup date [Wed Sep 05 12:20:08 CST 2018]; root of context hierarchy
2018-09-05 12:20:09.431  INFO 7140 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2018-09-05 12:20:09.443  INFO 7140 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2018-09-05 12:20:09.445  INFO 7140 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.27
2018-09-05 12:20:09.554  INFO 7140 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2018-09-05 12:20:09.554  INFO 7140 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1301 ms
2018-09-05 12:20:09.681  INFO 7140 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2018-09-05 12:20:09.684  INFO 7140 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-09-05 12:20:09.685  INFO 7140 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-09-05 12:20:09.685  INFO 7140 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-09-05 12:20:09.685  INFO 7140 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2018-09-05 12:20:09.733  INFO 7140 --- [           main] c.p.t.config.TestConfigInitializingBean  : --------------------------------------------
2018-09-05 12:20:09.733  INFO 7140 --- [           main] c.p.t.config.TestConfigInitializingBean  : -----正在執行InitializingBean實現類程式碼-----
2018-09-05 12:20:09.733  INFO 7140 --- [           main] c.p.t.config.TestConfigInitializingBean  : --------------------------------------------
2018-09-05 12:20:09.736  INFO 7140 --- [           main] com.port.test.config.TestPostConstruct   : --------------------------------------------
2018-09-05 12:20:09.736  INFO 7140 --- [           main] com.port.test.config.TestPostConstruct   : -----正在執行@PostConstruct實現類程式碼-----
2018-09-05 12:20:09.736  INFO 7140 --- [           main] com.port.test.config.TestPostConstruct   : --------------------------------------------
2018-09-05 12:20:09.969  INFO 7140 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot[email protected]140e5a13: startup date [Wed Sep 05 12:20:08 CST 2018]; root of context hierarchy
2018-09-05 12:20:10.038  INFO 7140 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : 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)
2018-09-05 12:20:10.039  INFO 7140 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : 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)
2018-09-05 12:20:10.066  INFO 7140 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-09-05 12:20:10.066  INFO 7140 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-09-05 12:20:10.098  INFO 7140 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-09-05 12:20:10.220  INFO 7140 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-09-05 12:20:10.229  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : --------------------------------------------
2018-09-05 12:20:10.230  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : -----正在執行ApplicationListener實現類程式碼-----
2018-09-05 12:20:10.230  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : --------------------------------------------
2018-09-05 12:20:10.290  INFO 7140 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2018-09-05 12:20:10.291  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : --------------------------------------------
2018-09-05 12:20:10.291  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : -----正在執行ApplicationListener實現類程式碼-----
2018-09-05 12:20:10.291  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : --------------------------------------------
2018-09-05 12:20:10.293  INFO 7140 --- [           main] c.p.t.c.TestConfigCommandLineRunner      : --------------------------------------------
2018-09-05 12:20:10.293  INFO 7140 --- [           main] c.p.t.c.TestConfigCommandLineRunner      : -----正在執行CommandLineRunner實現類程式碼-----
2018-09-05 12:20:10.293  INFO 7140 --- [           main] c.p.t.c.TestConfigCommandLineRunner      : --------------------------------------------
2018-09-05 12:20:10.293  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationRunner      : --------------------------------------------
2018-09-05 12:20:10.293  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationRunner      : -----正在執行ApplicationRunner實現類程式碼-----
2018-09-05 12:20:10.293  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationRunner      : --------------------------------------------
2018-09-05 12:20:10.294  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : --------------------------------------------
2018-09-05 12:20:10.294  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : -----正在執行ApplicationListener實現類程式碼-----
2018-09-05 12:20:10.294  INFO 7140 --- [           main] c.p.t.c.TestConfigApplicationListener    : --------------------------------------------
2018-09-05 12:20:10.295  INFO 7140 --- [           main] com.port.test.PortTestApp                : Started PortTestApp in 2.328 seconds (JVM running for 2.652)

相關推薦

Spring 容器初始呼叫介面

  在日常開發中難免會經常遇到這樣的應用場景,在專案初始化時執行指定的程式碼實現一些功能,或者在專案啟動後執行一些程式碼實現功能。這個時候就需要用到Spring提供的一些介面、註解了。本文都是以SpringBoot為基礎。 1.Spring容器啟動前執行    1.1介面

Spring初始InitializingBean介面和DisposableBean介面

     最近在看關於redis整合的程式碼的時候,配置jedis的擴充套件操作RedisTemplate類,其中有屬性設定jedis連線,忍不住好奇,看了看RedisTemplate的實現。發現RedisTemplate類繼承了RedisAccessor,而RedisAcc

Java HashMap 初始賦值

lec SM 解決 道理 test ack 增加 數據結構 解決辦法 1、HashMap 初始化的文藝寫法HashMap 是一種常用的數據結構,一般用來做數據字典或者 Hash 查找的容器。普通青年一般會這麽初始化:HashMap<String, S

03.Spring IoC 容器 - 初始

itl ret num servlet fontsize eat 圖片 number sources 基本概念 Spring IoC 容器的初始化過程在監聽器 ContextLoaderListener 類中定義。 具體由該類的的 configureAndRefreshWe

SpringBean初始的三種方法

常用的設定方式有以下三種: 通過實現 InitializingBean/DisposableBean 介面來定製初始化之後/銷燬之前的操作方法; 通過 <bean> 元素的 init-method/destroy-method屬性指定初始化之後 /銷燬之前呼叫的

springbean初始過程

在傳統的Java應用中,Bean的生命週期非常簡單。Java的關鍵詞new用來例項化Bean(或許他是非序列化的)。這樣就夠用了。相反,Bean 的生命週期在Spring容器中更加細緻。理解Spring Bean的生命週期非常重要,因為你或許要利用Spring提供的機會來訂製

JAVA陣列初始用new與不用new有區別嗎

不同於String類,String由於實現了常量池 所以new 和不new 有區別:new的話,引用變數指向堆區。不new的話,引用變數指向常量池。對於陣列的定義,初始化時用new與不用new 沒區別,

Springbean初始的三種方式

 (1)配置檔案    <!-- 1.構造方法例項化bean -->     <bean id="book" class="service."/>     <!-- 2.使用靜態工廠方法例項化bean ,由於方法是static,可以通過類名呼

SP2-1503: 無法初始 Oracle 呼叫介面 SP2-1503: 無法初始 Oracle 問題的解決辦法

win7 下   cmd  執行   sqlplus    報錯以下錯誤。 SP2-1503: 無法初始化Oracle 呼叫介面 SP2-1503: 無法初始化Oracle 調SP2-0152 解決辦法:  在oracle\product\10.2.0\db_2\BIN 目

Spring原始碼解讀-Spring IoC容器初始之資源定位

**IoC初始化過程 首先spring IoC容器的初始化,要分成三大部分,BeanDefinition的 Resource定位、載入和註冊三個基本過程。 今天我要說的就是資原始檔的定位,IoC容

Spring初始註解@PostConstruct

配置檔案: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://ww

Mybatis在spring容器初始過程

tsql tor 懶加載 alt onf mes text batis mybatis 由servlet容器調用容器啟動監聽器 spring的applicationContext刷新 實例化所有的單例(非懶加載的) beanNames:所有的單例(非懶加載的)的id,

spring容器初始bean的過程的時間週期

知識點介紹 1、 init-method方法,初始化bean的時候執行,可以針對某個具體的bean進行配置。init-method需要在 applicationContext.xml配置文件中bean的定義裡頭寫明。例如:<bean id="TestBean" cla

Java Web系統初始從資料庫載入資料到文字(ibatis,spring

有一些特殊情況,需要在系統初始化時載入一些配置屬性到本地文字中 web.xml <listener> <listener-class> org.springfra

Golang 引用庫含有初始代碼如何引用

usr nbsp 博文 str 符號 imp oca all 補充 簡單點說吧,要在引用庫前加‘_‘符號 給出示例 //foo.go // /usr/local/go/pkg/src/foo/foo.go package foo import "fmt" type Foo

Spring源碼分析總結(一)-IOC容器初始

Spring源碼分析總結一、IOC容器的初始化過程 IOC容器的初始化是由refresh()方法啟動。經常使用的ApplicationContext 有:ClassPathXmlApplicationContext和FileSystemXmlApplicationContext、XmlWebApp

spring原始碼學習之路---IOC容器初始要義之bean定義載入(四)

上章說到要帶各位去看看bean定義載入的要義,其實就是loadBeanDefinitions這個方法的具體實現步驟,下面我們跟隨這個方法去看下它到底是如何載入bean定義的。 上面是我擷取的實現了loadBeanDefinitions的類級別截圖,loadBeanDefinit

spring原始碼學習之路---深度分析IOC容器初始過程(三)

分析FileSystemXmlApplicationContext的建構函式,到底都做了什麼,導致IOC容器初始化成功。 public FileSystemXmlApplicationContext(String[] configLocations, boolean ref

spring容器初始bean之後或銷燬bean之前,能做的操作

通過 <bean> 標籤 init-method  初始化bean之後呼叫的方法 destroy-method  銷燬bean之前呼叫的操作方法 <bean id="initQuartzJob" class="com.upinc

linux3.3核心驅動初始具體呼叫的函式

system.map描述了程式碼具體的呼叫過程,對照這個過程,通過source-insight軟體搜尋到相應的初始化函式,整理如下: c0599ba4 t __initcall_init_static_idmapearly c0599ba4 T __initcall_start