SpringBoot自动配置
Condition
Condition是在Spring4.0增加的条件判断功能,通过这个功能可以实现选择性的创建Bean操作。
问题
SpringBoot是如何知道创建哪个Bean的?比如SpringBoot是如何知道要创建RedisTemplate的?
答案:SpringBoot会判断当前环境里有没有Redis里对应的字节码文件,实现Condition接口,然后重写matches方法,在matches方法中进行逻辑判断,返回一个boolean值,当bollean值为true时证明当前环境中就有Redis对应的字节码文件,就会创建当前这个Bean,没有就不会创建。(判断是否导入redis的依赖,如果导入了就会创建Bean,没有导入就不会创建)
SpringBoot提供的常用条件注解
- ConditionalOnProperty:判断配置文件中是否有对应的属性和值才初始化Bean
- ConditionalOnClass:判断环境中是否有对应的字节码文件,如果有才初始化Bean
- ConditionalOnMissingBean:判断环境中没有对应的Bean的时候才初始化Bean
SpringBoot切换内置web服务器
SpringBoot只要导入相关的依赖,就可以对服务器进行切换。
例:切换Tomcat前提
-
必须为web环境,@ConditionalOnWebApplication注解可以判断当前环境是否为web环境
-
是否拥有Tomcat.class和UpgradeProtocol.class文件,这两个文件需要导入Tomcat的依赖才会生成这两个文件。判断是否拥有这两个文件的注解为:@ConditionalOnClass
@Enable*相关的注解
SpringBoot中有很多Enable开头的注解,这些注解都是用于动态启用某些功能的。其底层原理是用@Import注解导入一些配置类,实现Bean的动态加载
问题:SpringBoot工程是否可以直接获取jar包中定义的Bean?为什么?那么如何解决呢?
答案:SpringBoot不能直接获取jar包中定义的Bean,因为@SpringBootApplication里面的@ComponentScan的包扫描范围是当前引导类所在包及其子包。
解决方法:
- 可以使用@ComponentScan扫描其它包(不推荐)
- 可以使用@Import注解来加载类,被加载的类都会被Spring创建,并放入IOC容器中来进行管理(不推荐)
- 对@Import注解进行封装
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)
public @interface EnableUser {
}
@Import注解
@Enable*相关注解的底层依赖于@Import,使用@Import注解可以把导入的类加载到spring的容器当中。而@Import注解提供4种用法:
- 导入Bean
- 导入配置类
- 导入ImportSelector实现类,一般用于加载配置文件中的类
- 导入ImportBeanDefinitionRegistrar实现类
@EnableAutoConfiguration注解(重要)
-
EnableAutoConfiguration注解内部使用了@Import(AutoConfigurationImportSelector.class)来加载配置类
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations; }
-
配置文件位置: META-INF/spring.factories,这个配置文件定义了大量的配置类,当SpringBoot项目启动的时候,会自动加载这些配置类,然后初始化Bean
-
并不是所有的Bean都会初始化,在配置类中使用Condition来加载满足条件的Bean