SpringBoot自动配置的注解是@EnableAutoConfiguration
所以来看@EnableAutoConfiguration注解的源码:
1、首先@EnableAutoConfiguration是包含在@SpringBootApplication组合注解中
2、使用@Import注入EnableAutoConfigurationImportSelector.class这个类
这里讲一下@Import注解:
@Import注解在4.2之前只支持导入配置类
在4.2,@Import注解支持导入普通的java类,并将其声明成一个bean
所以在Spring4.2之后就可以使用@Import既可以导入其他配置类,又可以导入一个普通的java类,并将其声明成一个bean。
所以我们重点来看一下EnableAutoConfigurationImportSelector.class
@Deprecated:从它的定义我们可以知道,它会被文档化,能够保留到运行时,能够修饰构造方法、属性、局部变量、方法、包、参数、类型。
代码解释:
首先EnableAutoConfigurationImportSelector继承了AutoConfigurationImportSelector类,并且重写了isEnabled方法。
isEnabled():
比较当前类是不是EnableAutoConfigurationImportSelector类。
所以核心加载配置列表的功能是在AutoConfigurationImportSelector中:
而这个方法中getCandidateConfigurations()去加载配置列表
这里和SpringBoot启动原理时去加载listener等配置文件时用相同的方式,通过SpringFactoriesLoader类的loadFactoryNames方法,去找当前META-INF/spring.factories文件。
而自动配置相关包是spring-boot-autoconfigure.jar,所以相应的spring.factories文件也在这个包下:
而在这些配置类中,随便点开一个发现,这些配置类会根据当前的条件注解的限制,会在不同的条件下去创建对应的Bean。
而条件注解相应的包在org.springframework.boot.autoconfigure.condition下:
@ConditionalOnBean:当容器里有指定的Bean的条件下
@ConditionalOnClass:当类路径下有指定的类的条件下
@ConditionalOnException:基于SpEL表达式作为判断条件
@ConditionalOnJava:在JNDI存在的条件下查找指定的位置
@ConditionalOnMissingBean:当容器里没有指定Bean的情况下
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下
@ConditionalOnNotWebApplication:当前项目不是web项目的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径是否有指定的值
@ConditionalOnSingleCandidate:当指定Bean在容器中只有一个,或者虽然有多个但是指定首选的Bean
@ConditionalOnWebApplication:当前项目是Web项目的条件下
上面这些注解都是组合了@Conditional元注解,只是使用了不同的条件(Conditional)
实例(自定义starter pom 当某个类存在的时候,自动配置这个类的Bean,并可将Bean的属性在application.properties中配置):
1、添加依赖:
这里的spring-boot-configuration-processor是配置处理器,处理配置。
2、属性配置:
这里是类型安全的获取。在application.properties中通过hello.msg =来设置,如果不设置,则默认为hello.msg=world.
3、判断依据类
这里是根据此类的存在与否来创建这个类的Bean,这个类可以是第三方类库的类
4、自动配置类
根据HelloServiceProperties中提供的参数,并通过@ConditionalOnClass判断HelloService这个类在类路径中是否存在,且当容器中没有这个Bean的情况下自动配置这个Bean。
5、注册配置
如果想要自动配置生效,需要注册自动配置类。在src/main/resources下新建META-INF/spring.factories,并填写如图所示的内容。
6、打包到本地
在idea内嵌maven插件,使用maven install 命令,打包到本地
7、新建springboot项目,添加依赖
此时,如果查看包结构,会发现,我们之前自定义的starter作为依赖被导入,并且根据相关条件已经自动配置
好相应的Bean。
8、使用自动配置的Bean
通过@Autowired注解,注入之前自动配置好的Bean。就可以对Bean进行操作
9、通过在application.properties中设置debug = true查看相应自动配置情况
此时,会发现,我们之前自定义的starter已经自动配置显示在控制台的报告中。