010-Spring Boot 擴展分析
一、常見的兩個擴展點
1、ApplicationContextInitializer
1.1、作用實現
作用:接口實在Spring容器執行refresh之前的一個回調。
Callback interface for initializing a Spring {@link ConfigurableApplicationContext}
實現:
/* * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *View Codehttp://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.*/ package org.springframework.context; /** * Callback interface for initializing a Spring {@link ConfigurableApplicationContext} * prior to being {@linkplain ConfigurableApplicationContext#refresh() refreshed}. * * <p>Typically used within web applications that require some programmatic initialization * of the application context. For example, registering property sources or activating * profiles against the {@linkplain ConfigurableApplicationContext#getEnvironment() * context‘s environment}. See {@code ContextLoader} and {@code FrameworkServlet} support * for declaring a "contextInitializerClasses" context-param and init-param, respectively. * * <p>{@code ApplicationContextInitializer} processors are encouraged to detect * whether Spring‘s {@link org.springframework.core.Ordered Ordered} interface has been * implemented or if the @{@link org.springframework.core.annotation.Order Order} * annotation is present and to sort instances accordingly if so prior to invocation. * * @author Chris Beams * @since 3.1 * @see org.springframework.web.context.ContextLoader#customizeContext * @see org.springframework.web.context.ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM * @see org.springframework.web.servlet.FrameworkServlet#setContextInitializerClasses * @see org.springframework.web.servlet.FrameworkServlet#applyInitializers */ public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> { /** * Initialize the given application context. * @param applicationContext the application to configure */ void initialize(C applicationContext); }
1.2、使用步驟
步驟一、寫一個類,實現ApplicationContextInitializer接口
步驟二、註冊ApplicationContextInitializer接口的實現
註冊方式
方式一、SpringApplication
SpringApplication application = new SpringApplication(App.class); application.addInitializers(new MyApplicationContextInitializer());
方式二、配置文件
context.initializer.classes=com.lhx.spring.springboot_enableauto.MyApplicationContextInitializer
多個用逗號隔開
方式三、使用spring.factories配置機制,註冊監聽器
在需要註入的項目包中添加META-INF/spring.factories
org.springframework.context.ApplicationContextInitializer=類名
1.3、使用:
新建一個:MyApplicationContextInitializer
package com.lhx.spring.springboot_enableauto; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("bean count:" + applicationContext.getBeanDefinitionCount()); // ConfigurableListableBeanFactory factory = // applicationContext.getBeanFactory(); } }View Code
調用
package com.lhx.spring.springboot_enableauto; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class App { public static void main(String[] args) { // ConfigurableApplicationContext context = SpringApplication.run(App.class, // args); SpringApplication application = new SpringApplication(App.class); application.addInitializers(new MyApplicationContextInitializer()); ConfigurableApplicationContext context = application.run(args); context.close(); } }View Code
2、CommandLineRunner、ApplicationRunner【類似開機自啟動】
2.1、作用於實現
作用:在spring容器全部初始化完畢,接口在容器啟動成功後的最後一步回調
* Interface used to indicate that a bean should <em>run</em> when it is contained within
* a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined
* within the same application context and can be ordered using the {@link Ordered}
* interface or {@link Order @Order} annotation.
實現
/* * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; /** * Interface used to indicate that a bean should <em>run</em> when it is contained within * a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined * within the same application context and can be ordered using the {@link Ordered} * interface or {@link Order @Order} annotation. * <p> * If you need access to {@link ApplicationArguments} instead of the raw String array * consider using {@link ApplicationRunner}. * * @author Dave Syer * @see ApplicationRunner */ public interface CommandLineRunner { /** * Callback used to run the bean. * @param args incoming main method arguments * @throws Exception on error */ void run(String... args) throws Exception; }View Code
2.2、使用步驟
步驟一、寫一個類實現CommandLineRunner接口
步驟二、把該類加入到Spring容器之中,可以通過@Order或Ordered接口控制順序,註解越小越先執行
2.3、使用
新建一個類ServerSuccessReport實現接口CommandLineRunner
package com.lhx.spring.springboot_enableauto; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class ServerSuccessReport implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("----CommandLineRunner執行-----"); } }View Code
註意同類接口
ApplicationRunner,
void run(ApplicationArguments args)
只是參數不一樣
CommandLineRunner是原始參數,沒有任何處理
ApplicationRunner是ApplicationArguments 對象,是對原始參數進一步的封裝
3.ApplicationArguments
是對參數(main方法)進一步重載
可以解析--name=value的,可以通過name獲取value
package com.lhx.spring.springboot_enableauto; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication application = new SpringApplication(App.class); ConfigurableApplicationContext context = application.run(args); ApplicationArguments arguments = context.getBean(ApplicationArguments.class); System.out.println(arguments.getSourceArgs().length); System.out.println(arguments.getOptionNames()); System.out.println(arguments.getOptionValues("name")); context.close(); } }
010-Spring Boot 擴展分析