Spring 自 3.2 引入 spring.factories SPI 后并没有真正的利用起来,使用的地方比较少,然而真正把 spring.factories 发扬光大的是在 Spring Boot 中
那在springboot中,spring.factories什么时候被加载的呢,里面的类又是什么时候被实例化的呢?
从一个普通的springboot项目的main方法进去
run方法启动
实例化SpringApplication
在实例化的过程中,会对一些内容进行初始化,其中就包括spring.factories的内容。
就是这里,一个读取里面的类全限定性类名,然后进行实例化。
加载
初始化
循环遍历,逐一初始化,用的是java的反射机制
反射, forName
public static Class<?> forName(String name, ClassLoader classLoader) throws ClassNotFoundException, LinkageError {
Assert.notNull(name, "Name must not be null");
Class<?> clazz = resolvePrimitiveClassName(name);
if (clazz == null) {
clazz = (Class)commonClassCache.get(name);
}
if (clazz != null) {
return clazz;
} else {
Class elementClass;
String elementName;
if (name.endsWith("[]")) {
elementName = name.substring(0, name.length() - "[]".length());
elementClass = forName(elementName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
} else if (name.startsWith("[L") && name.endsWith(";")) {
elementName = name.substring("[L".length(), name.length() - 1);
elementClass = forName(elementName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
} else if (name.startsWith("[")) {
elementName = name.substring("[".length());
elementClass = forName(elementName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
} else {
ClassLoader clToUse = classLoader;
if (classLoader == null) {
clToUse = getDefaultClassLoader();
}
try {
return Class.forName(name, false, clToUse);
} catch (ClassNotFoundException var9) {
int lastDotIndex = name.lastIndexOf(46);
if (lastDotIndex != -1) {
String nestedClassName = name.substring(0, lastDotIndex) + '$' + name.substring(lastDotIndex + 1);
try {
return Class.forName(nestedClassName, false, clToUse);
} catch (ClassNotFoundException var8) {
}
}
throw var9;
}
}
}
}