当前位置:   article > 正文

【JavaWeb】Day80.SpringBoot原理——自动配置(@Conditional)_spring自动配置 conditional

spring自动配置 conditional

自动配置@Conditional详解

        我们在跟踪SpringBoot自动配置的源码的时候,在自动配置类声明bean的时候,除了在方法上加了一个@Bean注解以外,还会经常用到一个注解,就是以Conditional开头的这一类的注解。以Conditional开头的这些注解都是条件装配的注解。下面我们就来介绍下条件装配注解。

@Conditional注解:

  • 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring的IOC容器中。
  • 位置:方法、类
  • @Conditional本身是一个父注解,派生出大量的子注解
  1. @ConditionalOnClass:判断环
  2. 判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器。
  3. @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

下面我们通过代码来演示下Conditional注解的使用:

@ConditionalOnClass注解

  1. ~~~java
  2. @Configuration
  3. public class HeaderConfig {
  4. @Bean
  5. @ConditionalOnClass(name="io.jsonwebtoken.Jwts")//环境中存在指定的这个类,才会将该bean加入IOC容器
  6. public HeaderParser headerParser(){
  7. return new HeaderParser();
  8. }
  9. }
  10. ~~~

pom.xml

  1. ~~~java
  2. <!--JWT令牌-->
  3. <dependency>
  4. <groupId>io.jsonwebtoken</groupId>
  5. <artifactId>jjwt</artifactId>
  6. <version>0.9.1</version>
  7. </dependency>
  8. ~~~

测试类

  1. ~~~java
  2. @SpringBootTest
  3. public class AutoConfigurationTests {
  4. @Autowired
  5. private ApplicationContext applicationContext;
  6. @Test
  7. public void testHeaderParser(){
  8. System.out.println(applicationContext.getBean(HeaderParser.class));
  9. }
  10. }
  11. ~~~

执行testHeaderParser()测试方法:

        因为io.jsonwebtoken.Jwts字节码文件在启动SpringBoot程序时已存在,所以创建HeaderParser对象并注册到IOC容器中。

@ConditionalOnMissingBean注解

  1. ~~~java
  2. @Configuration
  3. public class HeaderConfig {
  4. @Bean
  5. @ConditionalOnMissingBean //不存在该类型的bean,才会将该bean加入IOC容器
  6. public HeaderParser headerParser(){
  7. return new HeaderParser();
  8. }
  9. }

执行testHeaderParser()测试方法:

        SpringBoot在调用@Bean标识的headerParser()前,IOC容器中是没有HeaderParser类型的bean,所以HeaderParser对象正常创建,并注册到IOC容器中。

再次修改@ConditionalOnMissingBean注解:

  1. ~~~java
  2. @Configuration
  3. public class HeaderConfig {
  4. @Bean
  5. @ConditionalOnMissingBean(name="deptController2")//不存在指定名称的bean,才会将该bean加入IOC容器
  6. public HeaderParser headerParser(){
  7. return new HeaderParser();
  8. }
  9. }
  10. ~~~

执行testHeaderParser()测试方法:

        因为在SpringBoot环境中不存在名字叫deptController2的bean对象,所以创建HeaderParser对象并注册到IOC容器中。

再次修改 注解:

  1. ~~~java
  2. @Configuration
  3. public class HeaderConfig {
  4. @Bean
  5. @ConditionalOnMissingBean(HeaderConfig.class)//不存在指定类型的bean,才会将bean加入IOC容器
  6. public HeaderParser headerParser(){
  7. return new HeaderParser();
  8. }
  9. }
  10. ~~~
  1. ~~~java
  2. @SpringBootTest
  3. public class AutoConfigurationTests {
  4. @Autowired
  5. private ApplicationContext applicationContext;
  6. @Test
  7. public void testHeaderParser(){
  8. System.out.println(applicationContext.getBean(HeaderParser.class));
  9. }
  10. }
  11. ~~~

执行testHeaderParser()测试方法:

        因为HeaderConfig类中添加@Configuration注解,而@Configuration注解中包含了@Component,所以SpringBoot启动时会创建HeaderConfig类对象,并注册到IOC容器中。

        当IOC容器中有HeaderConfig类型的bean存在时,不会把创建HeaderParser对象注册到IOC容器中。而IOC容器中没有HeaderParser类型的对象时,通过getBean(HeaderParser.class)方法获取bean对象时,引发异常:NoSuchBeanDefinitionException。

 @ConditionalOnProperty注解(这个注解和配置文件当中配置的属性有关系)

先在application.yml配置文件中添加如下的键值对:

name: itheima

在声明bean的时候就可以指定一个条件@ConditionalOnProperty

  1. ~~~java
  2. @Configuration
  3. public class HeaderConfig {
  4. @Bean
  5. @ConditionalOnProperty(name ="name",havingValue = "itheima")//配置文件中存在指定属性名与值,才会将bean加入IOC容器
  6. public HeaderParser headerParser(){
  7. return new HeaderParser();
  8. }
  9. @Bean
  10. public HeaderGenerator headerGenerator(){
  11. return new HeaderGenerator();
  12. }
  13. }

执行testHeaderParser()测试方法:

修改@ConditionalOnProperty注解:  havingValue的值修改为"itheima2"

  1. ~~~java
  2. @Bean
  3. @ConditionalOnProperty(name ="name",havingValue = "itheima2")//配置文件中存在指定属性名与值,才会将bean加入IOC容器
  4. public HeaderParser headerParser(){
  5. return new HeaderParser();
  6. }
  7. ~~~

再次执行testHeaderParser()测试方法:

         因为application.yml配置文件中,不存在: name:  itheima2,所以HeaderParser对象在IOC容器中不存在。

我们再回头看看之前SpringBoot源码时提到的一个配置类:GsonAutoConfiguration

最后再给梳理一下自动配置原理:

        自动配置的核心就在@SpringBootApplication注解上,SpringBootApplication这个注解底层包含了3个注解,分别是:

  1. @SpringBootConfiguration
  2. @ComponentScan
  3. @EnableAutoConfiguration

@EnableAutoConfiguration这个注解才是自动配置的核心。

  • @Enable 开头的注解底层,它就封装了一个注解 import 注解,它里面指定了一个类,是 ImportSelector 接口的实现类。在实现类当中,重写了ImportSelector接口中的selectImports()方法。
  • 而selectImports()方法中会去读取两份配置文件,一份是 spring.factories,另外一份是 autoConfiguration.imports。而在  autoConfiguration.imports 这份文件当中,它会去配置大量的自动配置的类。并将配置文件中定义的配置类做为selectImports()方法的返回值返回,返回值代表的就是需要将哪些类交给Spring的IOC容器进行管理。
  • 那么所有自动配置类的中声明的bean都会加载到Spring的IOC容器中吗? 其实并不会,因为这些配置类中在声明bean时,通常都会添加@Conditional开头的注解,这个注解就是进行条件装配。而Spring会根据Conditional注解有选择性的进行bean的创建。只有条件成立,它才会声明这个bean,才会将这个 bean 交给 IOC 容器管理。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/987909
推荐阅读
相关标签
  

闽ICP备14008679号