本文是作者写关于Spring源码的第一篇文章,作者水平有限,所有的源码文章仅限用作个人学习记录。文中如有错误欢迎各位留言指正。
createSpringFactoriesInstances
上文说到读取配置文件spring.factories时,将读取到配置文件中的类进行实例化,现在来看这个方法。
java
// 参数分别是 类型,参数类型,类加载器,参数,类名称
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 {
// 这里又实用到了ClassUtils,使用这个工具类获取到这个类名称字符串的类型。这个工具类的forName方法的写法很好,我在很多方法都有看到类似的影子。
// 逻辑大概就是先判断是不是基础类型,如果不是就用类加载器进行加载
// 只要是我们自己定义的类就是这样Class.forName(name, false, clToUse);
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
// 判断type这个Class是不是instanceClass的超类
Assert.isAssignable(type, instanceClass);
// 找到Class的指定参数类型的构造方法
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;
}
实例化SpringApplication的构造方法分析完了,接下来就看看SpringApplication的成员方法run方法的逻辑。
run
这个方法有点多,不同版本也有一定的差异。
java
public ConfigurableApplicationContext run(String... args) {
// 为了计时用的,老版本和新版本不一样
long startTime = System.nanoTime();
// 初始化一个引导器的上下文,这是属于Spring Boot的上下文。后边还有一个Spring的上下文。apach好喜欢context这个东西,证明写框架这个context是真的好用。
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
createBootstrapContext
java
private DefaultBootstrapContext createBootstrapContext() {
// 通过无参构造实例化了一个对象
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
// 遍历SpringApplication的构造方法中读取spring.factories配置文件中BootStrapRegistryInitializer并实例化的对象,并调用它们的initialize方法,这是一个扩展点哟。如果我们给spring.factories中添加BootStrapRegistryInitializer的配置在这里也会执行
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}