(2)而下面这个run()方法,创建了一个SpringApplication对象,然后又调用了另外一个run方法。
(3)而这第三个run()方法refreshContext(ConfigurableApplicationContext context)拿到配置类,然后去解析配置类,主要是解析配置类上的注解@SpringBootApplication
(也就是这个启动类 )
那么,这个注解 @SpringBootApplication有什么呢?
2、注解@SpringBootApplication
包含了很多个注解,其中有**@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan**
(1)注解@SpringBootConfiguration
本质上,它是一个配置类
(2)注解@ComponentScan
它的作用是扫描当前包及其子包(这也是为什么有时我们把启动类放错位置,而导致无法扫描到某些包的原因)
(3)注解@EnableAutoConfiguration
它是自动装配的注解
@EnableAutoConfiguration上面加载了一个类,AutoConfigurationImportSelector类,该类会调方法getCandidateConfigurations()拿到配置
进入loadFactoryNames()方法,获取资源,并且完成资源文件spring-factories的读取
也就是说通过类加载classLoader,去加载META-INF下的spring-factories文件
并且加载系统中“META-INF/spring-factories”
那么, FACTORIES_RESOURCE_LOCATION中主要有什么呢?
以上面的 DataSource为例
可以看到,在spring-factories中配置了自动装配类
这个自动装配类会被读取到内存中
这个类本质上就是配置类,贴了注解@bean,也就是说这里会创建Datasource。
这个方法,返回的是一个DruidDataSoureWrapper
注解@ConfigurationProperties,作用是把配置文件中,前缀是Spring.datasource.druid的,注入到该对象。最后,框架拿到数据库的连接信息(账号密码等四要素),才能帮我们创建出Datasource。
特别地,贴了注解@ConditionalOnMissingBean(条件注解),代表着当前上下文中不存在该对象时,才会实例化一个Bean
@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean) @ConditionalOnNotWebApplication(不是web应用)
四、小结:自动装配的流程(原理)
1、main方法中SpringApplication.run(HelloBoot.class,args)的执行流程中有refreshContext(context)。
2、而这个refreshContext(context)内部会解析,配置类上自动装配功能的注解@EnableAutoConfiguration中的,@EnableAutoConfiguration中的,引入类AutoConfigurationImportSelector。