Condition是在Spring4.0增加的条件判断功能,通过这个功能可以实现选择性的创建Bean操作。
SpringBoot是如何知道创建哪个Bean的?比如SpringBoot是如何知道要创建RedisTemplate的?
答案:SpringBoot会判断当前环境里有没有Redis里对应的字节码文件,实现Condition接口,然后重写matches方法,在matches方法中进行逻辑判断,返回一个boolean值,当bollean值为true时证明当前环境中就有Redis对应的字节码文件,就会创建当前这个Bean,没有就不会创建。(判断是否导入redis的依赖,如果导入了就会创建Bean,没有导入就不会创建)
SpringBoot只要导入相关的依赖,就可以对服务器进行切换。
例:切换Tomcat前提
必须为web环境,@ConditionalOnWebApplication注解可以判断当前环境是否为web环境
是否拥有Tomcat.class和UpgradeProtocol.class文件,这两个文件需要导入Tomcat的依赖才会生成这两个文件。判断是否拥有这两个文件的注解为:@ConditionalOnClass
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 { }@Enable*相关注解的底层依赖于@Import,使用@Import注解可以把导入的类加载到spring的容器当中。而@Import注解提供4种用法:
导入Bean导入配置类导入ImportSelector实现类,一般用于加载配置文件中的类导入ImportBeanDefinitionRegistrar实现类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