文章目录
- Springboot源码分析
-
- 01、SpringBoot三大特性
- 02、传统的spring项目
- 03、springboot的项目:
- 04、如何去学习分析源码
- 05、springboot的零配置是怎么解决的
- 06、Springboot的零配置他们在解决一个什么问题
- 07、怎么认识项目中的bean
- 08、@Import机制,拯救第三方bean加载的IOC容器
- 09、四种机制的分析,如何把bean加载到IOC容器中
-
- 9.1、初始化阶段
- 9.2、运行阶段
- 9.3、如何和spring IOC 发生关系
- 9.4、spring生命周期的阶段
Springboot源码分析
01、SpringBoot三大特性
-
帮助开发者快速整合第三方框架(原理Maven依赖封装)
-
嵌入服务器(原理java语言创建服务器)
-
完全注解形式替代XML(原理包装Spring体系注解)
02、传统的spring项目
-
基于XMl形式
-
依赖的第三方的模块,都在pom.xml逐个依赖,还需要在xml文件中去配置
配置的目的就是让spring去加载和管理这些bean
-
需要依赖外部的tomcat容器去部署项目才可以进行项目发布与部署
-
日志管理,也需要额外的配置
-
配置组件或者应用非常的玛法和繁复
03、springboot的项目:
- 零配置,用注解的方式取代传统意义上的xml文件
- starter机制
- 内置了tomcat容器和日志管理。开发起来只需要启动main函数即可。就可以让项目运行起来了
- springboot管理的bean是如何注册spring IOC容器
04、如何去学习分析源码
- 心中一定有方向和目标
springboot项目的整体架构
核心启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootstudysourceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootstudysourceApplication.class, args);
}
}
05、springboot的零配置是怎么解决的
答案是用:注解
传统的ssm的方式的:
-
xml – applicationContext.xml
<bean id="xxx" class="xxx"> <bean id="xxx" class="xxx"> <bean id="xxx" class="xxx">
-
扫包 + 注解
<conpoment-scan basePackeges="com.kuangstudy.service"> <conpoment-scan basePackeges="com.kuangstudy.mapper"> <conpoment-scan basePackeges="com.kuangstudy.controller">
注解:@Service @Controller @RestController @Respostity @Component等
springboot改进
-
扫包 + 注解
@ComponentScan
-
@Configuration + @Bean配置类 + @Bean初始化
-
@Import 机制
@Import(配置列 & selector 即可实现类,你也可以写普通bean) @Import(RedisConfiguration.class) @Import(UserService.class) @Import(AxxxSelector.class)
-
@ImportResource
@ImportResource("classpath:applicationContext.xml")
06、Springboot的零配置他们在解决一个什么问题
- 抛弃传统的xml方式
- 也可以集成和整合传统的xml方式,通过@ImportResource。但是不建议混合使用
不管是传统的xml方式还是springboot提供的这四种机制,他们在解决什么问题?
他们都在解决同一个问题
通过不同的方式,把项目中的和第三方依赖全部通过这些机制,放入到spring的IOC容器中。springboot它的核心还是spring。它只不过是对spring这个框架进行了升级和改进。
07、怎么认识项目中的bean
项目中的bean
第三方的依赖 bean
解决方案:
-
扫包 + 注解(必须这些第三方的报名必须要和当前项目A包名要一致,否则加载不进去)
-
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(basePackages = { "org.mybatis", "com.alibaba.druid" })
上面的做法,肯定是不可取的。因为这种方式去加载第三方的bean,到项目中ioc去的,肯定非常麻烦,维护起来就是灾难。
08、@Import机制,拯救第三方bean加载的IOC容器
这个就是所谓的:start机制
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
官方提供的:spring-boot-starter-xxxx
第三方提供的:xxx-spring-boot-starter
两者的区别:官方不需要加版本号,因为通过parent指定的版本统一升级和管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
第三方的遵循springboot的starter机制开发出来的一种形式。它的导入就必须加version
09、四种机制的分析,如何把bean加载到IOC容器中
在启动springboot项目的时候
@SpringBootApplication
public class SpringbootstudysourceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootstudysourceApplication.class, args);
}
}
核心方法:
SpringApplication.run(SpringbootstudysourceApplication.class, args);
1. 调用方法如下
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
2. 调用方法如下
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
3. 重点
佐证一个观点:springboot是如何把bean放如到ioc容器中的
return (new SpringApplication(primarySources)).run(args);
# 拆解
// 初始化
SpringApplication application = new SpringApplication(primarySources);
// 运行阶段
application.run(args);
9.1、初始化阶段
new SpringApplication(primarySources)
初始化阶段:把项目中所有符合springboot机制的bean全部收集起来。map
1、调用构造函数方法
public SpringApplication(Class<?>... primarySources) {
this((ResourceLoader)null, primarySources);
}
2、调用具体的初始化方法过程(核心)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 1. 初始化数组,集合,开关标记
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 = Collections.emptySet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
this.applicationStartup = ApplicationStartup.DEFAULT;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 核心代码1
this.bootstrapRegistryInitializers = this.getBootstrapRegistryInitializersFromSpringFactories();
// 核心代码2
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 核心代码3
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
核心代码1 和 核心代码2 和 核心代码3 都在调用一个相同的方法:
核心代码1
可以看出,this.getBootstrapRegistryInitializersFromSpringFactories()
最终调用了
this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class)
核心代码2
this.getSpringFactoriesInstances(ApplicationContextInitializer.class)
核心代码3
this.getSpringFactoriesInstances(ApplicationListener.class)
三个都传递了一个类:
1:为什么要传递类?
- 触发类加载器
2:传递类的作用是干啥?
- 触发类加载器,通过双亲委派模型,把项目中所有的类,包括jdk、jdkext、target/classes、spring.jar、mybatis.jar 全部把他们中编译好的字节文件class找到,放入map中。
3:怎么找到项目所有需要的bean?
BootstrapRegistryInitializer
其实它这个类不是具体干活的类,它提前把项目中的类全部找到放入缓存map中,然后给ApplicationContextInitializer、ApplicationListener提供一个缓存机制,后面两者的获取对应bean就不会重复去触发类加载器,频繁的扫描过滤。
3、调用具体的 getSpringFactoriesInstances(核心)
下面就是类加载器:AppClassLoader – ExtClassLoader – BootstrapClassLoader(双亲委派模型)
ClassLoader classLoader = this.getClassLoader();
双亲委派模型:一句话,找到项目中所有的class文件,不论jdk、ext、项目写的class、spring.jar统统全部找到。
问:你项目中引入jdk是怎么加载进去的,你项目引入的spring.jar里面的类你为什么就可以使用。你项目String、List为什么就可以使用了呢?
答案:就是因为在启动的时候, 项目会调用类加载器通过双亲委派模型把项目中所有的class全部找到。然后放入到jvm中去,只不过springboot把这些加载到class进行过滤匹配把符合条件的bean放入到IOC容器中的过程。哪些是符合条件的bean呢?
- 扫包 + 注解(@Service, @Controller)
- 是不是符合import机制
- 是不是符合@Configuration + @Bean
4、开始对类加载器加载的类进行过滤
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
type:interface org.springframework.boot.Bootstrapper 开始进行匹配过滤。作用其实就是一个加载缓存的目的,作用就是:它会把类加载器中所有的jar文件包含 META-INF/spring.factories
文件中的内容全部找到。然后这个 META-INF/spring.factories
中的bean全部放入到Map中 如下:
5、把jar包中包含META-INF/spring.factories 的 找到
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
// 通过类加载器,把jar中包含META-INF/spring.factories的,找到
// 这里面的原理是双亲委派
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
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()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
String[] var10 = factoryImplementationNames;
int var11 = factoryImplementationNames.length;
for(int var12 = 0; var12 < var11; ++var12) {
String factoryImplementationName = var10[var12];
((List)result.computeIfAbsent(factoryTypeName, (key) -> {
return new ArrayList();
})).add(factoryImplementationName.trim());
}
}
}
result.replaceAll((factoryType, implementations) -> {
return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
});
cache.put(classLoader, result);
return result;
} catch (IOException var14) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
}
}
}
springboot是如何把需要的bean加载出来的呢?
我们知道类加载,把项目中所有的class统统都加载到jvm中。这么多的class,springboot是如何把需要管理和初始化放如IOC容器的class找出来的呢?springboot借鉴了java9的新特性:spi机制。这种机制其实就是把需要被加载类放入一个配置中,而springboot命名规则就是:META-INF/spring.factories。
- 而这个文件中就定义springboot需要加载的所有的bean,都放在这个文件中
- 现在要做的事情, 找到这个文件
- 解析这个文件
- 解析以后的bean,放入到map中(仅此而已,千万记住这个时候还没有和spring IOC产生关系)
找到第一个需要解析的jar包:
jar:file:/D:/ProgramFiles/apache-maven-3.6.3/.m2/org/springframework/boot/spring-boot/2.4.10/spring-boot-2.4.10.jar!/META-INF/spring.factories
# Logging Systems
org.springframework.boot.logging.LoggingSystemFactory=\
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
org.springframework.boot.logging.java.JavaLoggingSystem.Factory
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
# ConfigData Location Resolvers
org.springframework.boot.context.config.ConfigDataLocationResolver=\
org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\
org.springframework.boot.context.config.StandardConfigDataLocationResolver
# ConfigData Loaders
org.springframework.boot.context.config.ConfigDataLoader=\
org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\
org.springframework.boot.context.config.StandardConfigDataLoader
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer,\
org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer,\
org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PatternParseFailureAnalyzer,\
org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer
# Failure Analysis Reporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
找到第二个jar进行解析
URL [jar:file:/D:/ProgramFiles/apache-maven-3.6.3/.m2/org/springframework/spring-beans/5.3.9/spring-beans-5.3.9.jar!/META-INF/spring.factories]
org.springframework.beans.BeanInfoFactory=org.springframework.beans.ExtendedBeanInfoFactory
找到第三方jar
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
第四个需要解析的jar
URL [jar:file:/D:/ProgramFiles/apache-maven-3.6.3/.m2/org/springframework/boot/spring-boot/2.4.10/spring-boot-2.4.10.jar!/META-INF/spring.factories]
# Initializers
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.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer,\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
org.springframework.boot.autoconfigure.EnableAutoConfiguration
就是这个注解对应的所有的配置类。这些配置类,是如何加载到IOC容器中的呢?(运行阶段)
但是这些bean真的全部放进去吗? 答案:否
为什么初始化阶段还没有放入IOC容器中?
答:因为初始化阶段仅仅是一个解析和准备的工作,就把需要的bean全部找到,仅此而已。
Application Context Initializers
org.springframework.context.ApplicationContextInitializer=
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,
org.springframework.boot.context.ContextIdApplicationContextInitializer,
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
Run ---- 1 2 3 4 5 6 7 -----selectImports
1: 执行run方法
2:
this.refreshContext(context);
3:
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();
}
4:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
5:
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
6:
postProcessor.postProcessBeanDefinitionRegistry(registry);
7:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
parser.parse(candidates);
public void processGroupImports() {
Iterator var1 = this.groupings.values().iterator();
while(var1.hasNext()) {
ConfigurationClassParser.DeferredImportSelectorGrouping grouping = (ConfigurationClassParser.DeferredImportSelectorGrouping)var1.next();
Predicate<String> exclusionFilter = grouping.getCandidateFilter();
grouping.getImports().forEach((entry) -> {
ConfigurationClass configurationClass = (ConfigurationClass)this.configurationClasses.get(entry.getMetadata());
try {
ConfigurationClassParser.this.processImports(configurationClass, ConfigurationClassParser.this.asSourceClass(configurationClass, exclusionFilter), Collections.singleton(ConfigurationClassParser.this.asSourceClass(entry.getImportClassName(), exclusionFilter)), exclusionFilter, false);
} catch (BeanDefinitionStoreException var5) {
throw var5;
} catch (Throwable var6) {
throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configurationClass.getMetadata().getClassName() + "]", var6);
}
});
}
}
Application Listeners
org.springframework.context.ApplicationListener=
org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.context.logging.LoggingApplicationListener,
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener,
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
9.2、运行阶段
.run(args)
把初始化阶段所有收集的bean,全部初始化放入到IOC容器中,再去经历spring生命周期,运行结束。
证明:启动类在启动默认情况下,会把当前主类的包名作为包入口
也就是@ComponentScan 的原理。其实它背后有一个类在做事情。如下:
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
但是注意:是run()运行阶段做的事情
如何证明:注解的解析和放入IOC是在运行阶段去执行和解析的呢?
-
初始化的构造函数结束行打个断点 —> run方法开头打个断点 —> 在解析类中打个断点
如果是按照这个执行的话,说明初始化阶段仅仅就解析spring.factories 这个文件和收集对应需要初始化的bean。并且证明注解的解析和bean初始化都是在run方法中执行
-
初始化的构造函数结束行打个断点 —> 在解析类中打个断点(错误)
9.3、如何和spring IOC 发生关系
run方法执行:this.refreshContext(context);
9.4、spring生命周期的阶段
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}