创建一个SpringBoot项目,核心文件只有两个,一个是main方法的启动类文件,一个是application.properties全局配置文件。究竟是怎么运行,请看如下分析:
-
原理一览图:
-
解释一下
-
@SpringBootConfiguration:是Spring的一个组件。证明如下:
-
@EnableAutoConfiguration:自动配置的核心注解
-
@ComponentScan:扫描主启动类同级下的包
@EnableAutoConfiguration
通过@Import({AutoConfigurationImportSelector.class}),导入自动配置的核心类AutoConfigurationImportSelector :
-
该类的核心方法:selectImports()
-
调用 isEnabled():
通过三目运算符判断,如果需要自动装配则返回目标类型true,原因请看方法 getProperty()。 -
调用 getProperty():
最后一个参数var3就是要返回的目标类型。
当返回true之后,就会执行selectImports()方法的else分支中的语句: -
调用 getAutoConfigurationEntry() 方法获得自动配置实体
-
调用 getCandidateConfigurations() 方法获得候选的配置,我们可以看下 断言,说找不到META-INF/spring.factories,由此可见,这个方法是用来找META-INF/spring.factories文件的
-
调用 getSpringFactoriesLoaderFactoryClass()
获得有@EnableAutoConfiguration注解的类的所有属性配置。 -
调用 SpringFactoriesLoader.loadFactoryNames()
-
调用 loadSpringFactories()
-
spring.factories文件, 这个文件的内容都是key-value的形式,一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔。
诸多的xxxxAutoConfiguration自动配置类, 目的是给容器中添加组件,就是Spring容器的JavaConfig形式,而所有导入的bean所需要的属性都通过xxxxProperties的bean来获得,xxxxProperties 主要作用是封装配置文件中相关属性。@EnableAutoConfiguration注解被间接的标记在了SpringBoot的主启动类上,SpringApplicaton.run方法就会执行selectImports方法,进而找到所有配置类全限定名对应的class,然后将所有自动配置类加载到Spring的IOC容器中。
举例文件中的一个自动配置类 MongoDataAutoConfiguration:
@EnableConfigurationProperties负责将绑定后的bean导入Spring容器。
@ConfigurationProperties将配置文件中的属性绑定到bean上。
自动配置如何生效:
满足以@Conditional注解为核心注解的后面括号内的条件就可以生效自动配置,一但这个配置类生效,这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定。这就造成了配置文件可以动态的修改SpringBoot的一些内容。
例如:
总结:(从1到5是连续的,为了读者看的方便就分开写了,如有错误请多多指教)
- 自动装配就是通过 @EnableAutoConfiguration 注解找到Spring提供的自动配置总文件 spring.factories中的 所有自动装配类并对其进行加载,这个文件是一组组的 key=value的形式,包含了key为EnableAutoConfiguration的全类名,value是一个xxxxAutoConfiguration类名的 列表,以逗号分隔;
- 这也是JavaConfig形式的IOC容器配置类,在每个value所指的类中,都有 @ConditionalOnxxxx 这种类型的注解,会根据这种类型的注解决定判断条件(在该注解后面的圆括号内)是否满足,条件满足才进行自动装配;
- 每个自动配置类上都有一个 @Configuration和该类的每个方法上面都有一个 @Bean,@Configuration可理解为用spring的时候beans.xml里面的beans标签,作用是告诉SpringBoot这是一个配置类;@Bean可理解为用spring的时候beans.xml里面的bean标签,@Bean标签的作用是给容器中添加组件,以@Bean所标记的方法的方法名作为组件的id名,返回类型就是组件类型,方法返回的值就是组件在容器中的实例;
- 每个自动配置类上面又都有 @EnableConfigurationProperties注解,通过这个注解将封装好的bean导入到Spring的IOC容器中;
- 在 @EnableConfigurationProperties 注解注入的bean中,每个bean 都有 @ConfigurationProperties 注解,该注解负责将配置文件中的属性绑定到对应的xxxxProperties配置实体类上封装为一个具体的bean;
- 全局配置(application.properties)文件中的属性,也是通过 @ConfigurationProperties 注解指定的 前缀prefix绑定到对应的 xxxxPropertie 配置实体类上封装为一个bean,然后再通过 @EnableConfigurationProperties注解导入到Spring的IOC容器中。在全局配置文件中,如果需要到的属性没有进行配置,则使用默认的(自动装配的)组件中的属性,这也是约定大于配置的体现(SpringBoot都进行了约定(配置好了),开发人员能配置得更少,更直接地开发项目,写业务逻辑代码),待完成总配置文件的属性绑定和注入之后,SpringBoot完成最终的自动装配。