第一种:定义在spring.factories中被SpringFactoriesLoader发现注册
通过模仿源码实现,代码如下:
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.*;
/**
* @Auth : HUANG GUOYE.
* @Date : 2020/3/22
* @Desc : mooc-study
*/
public class Test01 {
public static void main(String[] args) {
Test01 test01 = new Test01();
List<Object> list = test01.test001(ApplicationContextInitializer.class);
test01.action(list);
}
/**
* 获取系统初始化器的实例demo
* 1.获得类加载器的reference
* 2.获得接口系统初始化器接口(ApplicationContextInitializer)名称
* 3.取文件classLoader.getResources("META-INF/spring.factories")
META-INF/spring.factories:org.springframework.context.ApplicationContextInitializer=com.mooc.study.initializer.FirstInitializer
* 4.转properties,
* 5.取值进集合
* 6.反射实例
* 7.排序
*/
private <T> List<Object> test001(Class<T> type){
List<Object> instances = new ArrayList<>();
Set<String> result = new HashSet<>();
//1.获得类加载器的reference
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
//2.获得接口系统初始化器接口(ApplicationContextInitializer)名称
// Class<ApplicationContextInitializer> applicationContextInitializerClass = ApplicationContextInitializer.class;
String clazzName = type.getName();
//3.取文件classLoader.getResources("META-INF/spring.factories")
try {
Enumeration<URL> resources = classLoader.getResources("META-INF/spring.factories");
while (resources.hasMoreElements()) {
//4.转properties,
URL url = resources.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
//5.取值进集合
while (iterator.hasNext()) {
Map.Entry<Object, Object> entry = iterator.next();
//只要自己的配置,其余的不要
if (clazzName.equals(entry.getKey())) {
String[] arr = String.valueOf(entry.getValue()).trim().split(",");
for (String str : arr) {
result.add(str);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", e);
}
//6.反射实例
for (String e : result) {
try {
Class<?> aClass = Class.forName(e);
//判断配置的对还是错,是不是该接口的实现类
Assert.isAssignable(type, aClass);
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
Object instance = BeanUtils.instantiateClass(declaredConstructor, new Class[0]);
instances.add(instance) ;
} catch (ClassNotFoundException e1 ) {
throw new IllegalArgumentException("Cannot instantiate " + clazzName + " : " + e, e1);
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
}
//7.排序
instances.sort((o1,o2)->{
int i1 = Integer.MAX_VALUE ;
Order order1 = o1.getClass().getAnnotation(Order.class);
if(null != order1){
i1 = order1.value();
}
int i2 = Integer.MAX_VALUE ;
Order order2 = o2.getClass().getAnnotation(Order.class);
if(null != order2){
i2 = order2.value();
}
return i1 - i2;
});
return instances ;
}
/**
* 8.调用实例方法
* @param list
*/
private void action(List<Object> list ){
ConfigurableApplicationContext context = null ;
try {
Class<?> aClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
Object instance = BeanUtils.instantiateClass(declaredConstructor, new Class[0]);
context = (ConfigurableApplicationContext) instance;
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
}
for (Object o : list) {
ApplicationContextInitializer initializer = (ApplicationContextInitializer)o ;
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
ConfigurableEnvironment environment = context.getEnvironment();
String value = environment.getProperty("key1");
System.out.println("value="+value);
}
}
第二种:SpringApplication初始化完毕后,手动添加
1.启动springboot项目
/**
* 配置自定系统初始化器
* springapp
*/
SpringApplication springApplication = new SpringApplication(Application.class);
//手动添加自定义初始化器
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);
2.硬编码,手动添加实例
/**
* Add {@link ApplicationContextInitializer}s to be applied to the Spring
* {@link ApplicationContext}.
* @param initializers the initializers to add
*/
public void addInitializers(ApplicationContextInitializer<?>... initializers) {
//硬编码,手动添加实例
this.initializers.addAll(Arrays.asList(initializers));
}
3.调用实例的initialize方法
/**
* Apply any {@link ApplicationContextInitializer}s to the context before it is
* refreshed.
* @param context the configured ApplicationContext (not refreshed yet)
* @see ConfigurableApplicationContext#refresh()
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
//获取泛型类,判断是否是需要的类
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
//调用实现方法
initializer.initialize(context);
}
}
第三种:定义成环境变量,被DelegatingApplicationContextInitializer发现注册
1.调用DelegatingApplicationContextInitializer的initialize方法,获取环境变量(
context.initializer.classes=com.mooc.study.initializer.ThirdInitializer
)-class-instance-initialize
@Override
public void initialize(ConfigurableApplicationContext context) {
//获取环境变量
ConfigurableEnvironment environment = context.getEnvironment();
//获取context.initializer.classes定义的类,反射->class
List<Class<?>> initializerClasses = getInitializerClasses(environment);
if (!initializerClasses.isEmpty()) {
applyInitializerClasses(context, initializerClasses);
}
}
2.通过反射获得class
private List<Class<?>> getInitializerClasses(ConfigurableEnvironment env) {
String classNames = env.getProperty(PROPERTY_NAME);
List<Class<?>> classes = new ArrayList<>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
//反射
classes.add(getInitializerClass(className));
}
}
return classes;
}
3.通过反射获得实例
private void applyInitializerClasses(ConfigurableApplicationContext context, List<Class<?>> initializerClasses) {
Class<?> contextClass = context.getClass();
List<ApplicationContextInitializer<?>> initializers = new ArrayList<>();
for (Class<?> initializerClass : initializerClasses) {
//反射进集合
initializers.add(instantiateInitializer(contextClass, initializerClass));
}
applyInitializers(context, initializers);
}
4.调用实现方法
private void applyInitializers(ConfigurableApplicationContext context,
List<ApplicationContextInitializer<?>> initializers) {
initializers.sort(new AnnotationAwareOrderComparator());
for (ApplicationContextInitializer initializer : initializers) {
//调用实现方法
initializer.initialize(context);
}
}