springboot源码(四)
springboot入口run方法细节分析
上一篇主要说了一下SpringApplication的构造方法和 run 方法里面都做了哪些事情,这一篇具体分析一下里面的主要方法。
1、//将spring.factories中key为ApplicationContextInitializer对应的类型实例化后放到成员变量initializers里
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
分析一下该方法:
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // type=ApplicationContextInitializer 加载spring.factories中key为ApplicationContextInitializer,将全类路径名存放到names中 Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 根据names中的全类路径名创建实例 List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) { List<T> instances = new ArrayList<>(names.size()); for (String name : names) { try {
//通过反射的方式得到类 Class<?> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass);
//创建构造器进行实例化 Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes); T instance = (T) BeanUtils.instantiateClass(constructor, args); instances.add(instance); } catch (Throwable ex) { throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex); } } return instances; }
2、//将spring.factories中key为ApplicationListener的对应类型实例化后放到SpringApplication的成员变量listener里
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
分析一下:
大致过程跟setInitializers()方法是一样的,就是把spring.factories中的ApplicationListener的对应类型的实例化放到SpringApplication的成员变量listeners中。
3、//反推main方法所在的类对象,并记录在mainApplicationClass中
this.mainApplicationClass = this.deduceMainApplicationClass();
分析一下如何反推回main方法所在的class对象的:
StackTrace:
我们在学习函数调用时,就知道了每个函数都拥有自己的栈空间。
一个函数被调用时,就创建一个新的栈空间,那么通过函数的嵌套调用最后就形成了一个函数调用堆栈。
所以,StackTrace就是记录了程序方法执行的链路。
debug形式查看函数调用栈:
private Class<?> deduceMainApplicationClass() { try {
//获取当前方法执行的堆栈信息 StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); for (StackTraceElement stackTraceElement : stackTrace) {
//判断是否是main方法,如果是返回main方法对应的class对象 if ("main".equals(stackTraceElement.getMethodName())) { return Class.forName(stackTraceElement.getClassName()); } } } catch (ClassNotFoundException ex) { // Swallow and continue } return null; }
4、分析run方法中的比较重要的方法
//加载SpringApplicationRunListener得到事件发布器EventPublishingRunListener,会把SpingringApplication中的成员变量listener放到listeners中 SpringApplicationRunListeners listeners = this.getRunListeners(args);
private SpringApplicationRunListeners getRunListeners(String[] args) {
//声明了一个参数类型数组,其中有一个是SpringApplication类型 Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
//将参数数组types作为参数传递给很熟悉的getSpringFactoriesInstances()方法 return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)); }
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // 加载spring.factories中SpringApplicationRunListener类型:EventPublishingRunListener(事件发布器) Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//创建EventPublishingRunlistener实例 List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) { List<T> instances = new ArrayList<>(names.size()); for (String name : names) { try { Class<?> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass);
//EventPublishingRunlistener的构造器参数分别为SpringApplication和String[],所以EventPublishingRunListener事件发布器就加载到所有SpringApplication中listeners变量中的全部ApplicationListener Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes); T instance = (T) BeanUtils.instantiateClass(constructor, args); instances.add(instance); } catch (Throwable ex) { throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex); } } return instances; }
//EventPublishingRunlistener类源码
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SpringApplication application; private final String[] args; private final SimpleApplicationEventMulticaster initialMulticaster; public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.initialMulticaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } }
到这,基本上就知道了run方法都大致干了些什么勾当。下一篇分析springboot监听器的设计。