SpringBoot源码分析
Springboot源码分析1、SpringApplication初始化
从run()方法进入,可以看到Springboot起首创建了SpringApplication,然后调用SpringApplication的run()方法。
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}创建SpringApplication,起首要执行它的构造方法。
//SpringApplication.class
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
//webApplication类型一般是servlet
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//设置初始化器,加载spring.factories文件中的ApplicationContextInitializer
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设置监听器,加载spring.factories文件中的ApplicationListener
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//启动类的类型,我们的是com.example.demo.DemoApplication
this.mainApplicationClass = this.deduceMainApplicationClass();
}1.1 & 1.2 设置初始化器和监听器
上面的setInitializers和setListeners去初始化spring.factories文件中对应的类,然后放入ArrayList中。比如这些:
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer1.2.1 getSpringFactoriesInstances
在getSpringFactoriesInstances()方法中,springboot起首去所有spring.factories找到对应的类,然后通过反射创建类的实例。
//SpringApplication.class
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return this.getSpringFactoriesInstances(type, new Class);
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = this.getClassLoader();
//获取spring.factories中对应类的类名,以ApplicationListenser为例,springboot会去文件中找到所有ApplicationListener对应的类,放入Set中。
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//反射创建类的实例对象,放到List中返回
List<T> instances = this.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());
Iterator var7 = names.iterator();
while(var7.hasNext()) {
String name = (String)var7.next();
try {
//获取类信息
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
//获取构造器
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
//创建实例
T instance = BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
} catch (Throwable var12) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
}
}
return instances;
}1.2.2 loadFactoryNames()
进入SpringFactoriesLoader.loadFactoryNames(type, classLoader)看一下,这里还是以ApplicationListener为例,这时的type是org.springframework.context.ApplicationListener,classLoader是AppClassLoader。
//SpringFactoriesLoader.class
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
MultiValueMap<String, String> result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Map.Entry<?, ?> entry = (Map.Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryImplementationName = var9;
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location ", var13);
}
}
}loadSpringFactories()方法会遍历所有的spring.factories文件,把所有的类的名字生存到map中,然后调用getOrDefault()方法就可以获取到所有的ApplicationListner对应的类名了。
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160505463-811496707.png
SpringApplication初始化完了,接下来该执行run()方法了
2、SpringApplication执行run()方法
//SpringApplication.class
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//这里是Spring的上下文
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
//获取运行监听器,获取到的是EventPublishingRunListener,这是springboot的启动监听器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//启动监听器
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//2.1 准备环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
//Banner打印类
Banner printedBanner = this.printBanner(environment);
//2.2 创建应用上下文
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//2.3 准备上下文
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//2.4 刷新上下文
this.refreshContext(context);
//刷新上下文后置处理
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
//发布上下文启动完成事件
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}2.1 prepareEnvironment()准备环境
//SpringApplication.class
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
//根据前面推断的webApplicationType创建对应的环境,servlet对应的是StandardServletEnvironment()
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
//根据参数配置环境,包括命令行参数,启动类传入的参数
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
//执行完这个,配置文件中的配置进行就被加载到环境中了
listeners.environmentPrepared((ConfigurableEnvironment)environment);
//环境和SpringApplication绑定起来
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}2.1.1 根据参数配置环境configureEnvironment()
//SpringApplication.class
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService)conversionService);
}
//配置命令行中的参数
this.configurePropertySources(environment, args);
//激活相应的配置文件,例如application.propertires或者application-dev.properties等
this.configureProfiles(environment, args);
}如果我启动的dev环境,执行完上面的代码后环境中是这样的
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160505065-376220975.png
2.1.2 listeners.environmentPrepared()
执行完这句代码后,配置文件中的信息就被加载到环境中了,如下图。具体怎么做到的还没看懂
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160504680-843829619.png
2.2 创建应用上下文createApplicationContext()
//SpringApplication.class
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
}
} catch (ClassNotFoundException var3) {
throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
}
}
return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}这个函数也是根据前面的webApplicationType创建应用上下文,servlet对应的是AnnotationConfigServletWebServerApplicationContext,当初始化完这个类时,其实也会创建一个IOC容器beanFactory,如下图所示。这是因为AnnotationConfigServletWebServerApplicationContext会继承GenericApplicationContext,当执行完这个类的构造函数,会创建一个DefaultListableBeanFactory()的beanFactory,这个就是IOC容器。
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160504223-854337640.png
2.3 准备上下文prepareContext()
//SpringApplication.class
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
//设置上下文环境
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
//初始化所有的ApplicationContextInitializer
this.applyInitializers(context);
//发布上下文准备完成事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
//获取IOC容器beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//将springApplicationArguments和springBootBanner注册成单例
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
//2.3.1 获取资源,其中primarySources就是我们定义的启动类DemoApplication
Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//2.3.2 加载启动类,注入IOC容器
this.load(context, sources.toArray(new Object));
//发布完成加载事件
listeners.contextLoaded(context);
}2.3.1 & 2.3.2 获取启动类,注入IOC容器
当执行完getAllSources(),可以获取到启动类DemoApplication
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160503857-611438687.png
重点看load()方法,进入load()。
//SpringApplication.class
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//创建BeanDefinitionLoader
BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
//加载启动类
loader.load();
}其中getBeanDefinitionRegistry(context)方法会将之前的上下文context强转成BeanDefinitionRegistry,他们之间的继承关系很复杂,可以转换成不同的类完成不同的方法。createBeanDefinitionLoader()方法创建了一个BeanDefinitionLoader(),点进去看看。
//BeanDefinitionLoader.class
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
//注解形式的Bean阅读器
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
//xml形式的Bean阅读器
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (this.isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
//类路径扫描器
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}一直跟进load()。
//BeanDefinitionLoader.class
private int load(Class<?> source) {
if (this.isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
GroovyBeanDefinitionSource loader = (GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
this.load(loader);
}
//启动类会走进这里
if (this.isEligible(source)) {
//将启动类注册进beanDefinitionMap
this.annotatedReader.register(new Class[]{source});
return 1;
} else {
return 0;
}
}进入register()方法。
//AnnotatedBeanDefinitionReader.classpublic void register(Class... componentClasses) { Class[] var2 = componentClasses; int var3 = componentClasses.length; for(int var4 = 0; var4 < var3; ++var4) { Class componentClass = var2; this.registerBean(componentClass); }}public void registerBean(Class beanClass) { this.doRegisterBean(beanClass, (String)null, (Class[])null, (Supplier)null, (BeanDefinitionCustomizer[])null);}privatevoid doRegisterBean(Class beanClass, @Nullable String name, @Nullable Class
页:
[1]