springboot的@ConditionalOnBean注解(springboot configuration注解详解)

  本篇文章为你整理了springboot的@ConditionalOnBean注解(springboot configuration注解详解)的详细内容,包含有springboot conditionalonbean springboot configuration注解详解 springboot condition springboot conditiononmisson springboot的@ConditionalOnBean注解,希望能帮助你了解 springboot的@ConditionalOnBean注解。

    上篇文章中分析了springboot的自动注入的原理,可在文章后面的推荐阅读中温习哦。在自动注入的原理那篇文章中提到了@ConditionalOnXX注解,今天来看下springboot中的@ConditionalOnXX注解,该注解表示的是一类注解。马上开始吧。

  一、@ConditionalOnXX注解初识

   @ConditionalOnXX注解被定义在了spring-boot-autoconfigure包中,有以下几个,

    从上图中可以看到经常碰到的@ConditionalOnBean、@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnMissingClass、@ConditionalOnProperty、@ConditionalOnResource、@ConditionalOnSingleCandidate等。这些注解均在”org.springframework.boot.autoconfigure.condition“包下,感兴趣的小伙伴可以自行查看源码。

  二、深入@ConditionalOnBean注解

    上面提到了多个@ConditionalOnXX注解,下面逐一对这些常见的注解进行讲解。有意思的是,这些注解很多都是成对出现的,而且意思都是相近的。今天先来看下@CondtionalOnBean注解

  2.1、@ConditionalOnBean

    @ConditionalOnBean注解的定义如下,

    可以明确的一点是@ConditionalOnBean可以用在类/方法上。可以配置的属性有下面这些,

    平时用的比较多的有value、type、name三个,这三个可以看到都是数组,也就是说可以配置多个。

    上面提到@ConditionalOnBean可以配置在方法上,是所有的方法都可以吗?

  2.2、@ConditionalOnBean如何标识方法

    @ConditionalOnBean标识在方法上,可以标识在所有的方法上吗,这个我们要从该注解的注释上去找答案了。

    从上面的注释可以知道,@ConditionalOnBean注解使用在@Bean标识的方法上,都知道@Bean注解的作用是向容器中注入一个bean,也就是@ConditionalOnBean作用的时机是在生成bean的时候。再看注释“the bean class defaults to return type of the factory method”,大体意思是默认返回的bean是工厂方法的类型,这个不好理解,通过一个例子看下。

  2.2.1、@ConditionalOnBean(value=)

  MyAutoConfig.java

  

package com.my.template.config;

 

  import org.springframework.boot.autoconfigure.AutoConfigureAfter;

  import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;

  import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

  import org.springframework.context.annotation.Bean;

  import org.springframework.context.annotation.Configuration;

   * 配置类

   * @date 2022/7/2 15:02

  @Configuration

  public class MyAutoConfig {

   @Bean(value = "classA")

   public ClassA classA(){

   return new ClassA();

   @Bean

   @ConditionalOnBean(value = {ClassA.class})

   public ClassB classB(){

   return new ClassB();

  }

 

  在上面的配置类中,在@Bean注解的方法上使用了@ConditionalOnBean注解,注解中使用的value属性,代表的是只要存在ClassA这个类边会执行classB()方法,下面看ClassA和ClassB都很简单,就是两个普通的类,

  ClassA.java和ClassB.java

  

package com.my.template.config;

 

   * @date 2022/7/2 15:03

  public class ClassA {

   public ClassA() {

   System.out.println("constructor classA");

  package com.my.template.config;

   * @date 2022/7/2 15:04

  public class ClassB {

   public ClassB() {

   System.out.println("constructor classB");

  }

 

  看下启动日志是否会打印构造方法中的日志,

  可以看到正常打印了,也就是说ClassA和ClassB均被注入到了容器中,这是使用@ConditionalOnBean(value=)的情况,下面看使用@ConditionalOnBean(type=)的情况,

  2.2.2、@ConditionalOnBean(type=)

  这里的type要求填入的是类的全路径,比如com.my.template.config.ClassA

  把配置类中修改为下面的样子,

  再次启动观察日志,

  从日志中可以看到依旧是可以的,下面我把MyAutoConfig类中的classA()方法,放到classB()方法下面,

  再执行看日志,

  可以看到没有执行ClassB的构造方法,也就是classB()方法没执行。可以得出:在配置类中的@Bean标识的方法是有顺序的,前边的会先解析,后边的后解析,后面的要引用前面的是引用不到的,反之则可以。

  这种方式下,没有其他方式可以执行classB()方法吗,有的,使用@ConditionalOnClass(value={ClassA.class}),感兴趣的小伙伴可以自己试试哦。

  2.2.3、@ConditionalOnBean(name=)

  下面看使用name属性的情况,

  MyAutoConfig.java修改成下面的样子,

  启动日志如下,

  正常启动,且初始化了ClassB类。

  2.3、ConditionalOnBean标识类

    这里说的标识类,我们一般都默认为标识配置类,即带有@Configuration注解的类。这里同时会有value、type、name三种不同的属性配置,需要注意的是value配置的是Class对象,标识的是只要在解析过程中加载了该类即可。type配置的是全类名,name配置的是bean的名称,type和name的配置要求的是需要解析了该BeanDefinition,同时和顺序是有关系的。演示下面的例子

  MyAutoConfig.java

  

package com.my.template.config;

 

  import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;

  import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

  import org.springframework.context.annotation.Bean;

  import org.springframework.context.annotation.Configuration;

   * 自动配置类

   * @date 2022/7/2 15:02

  @Configuration

  @ConditionalOnBean(type = {"com.my.template.config.ClassA"})

  public class MyAutoConfig {

   public MyAutoConfig(){

   System.out.println("constructor MyAutoConfig");

  }

 

  MyAutoConfig2.java

  

package com.my.template.config;

 

  import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;

  import org.springframework.context.annotation.Bean;

  import org.springframework.context.annotation.Configuration;

   * 自动配置类

   * @author wangcj5

   * @date 2022/7/2 15:02

  @Configuration

  public class MyAutoConfig2 {

   @Bean

   public ClassA classA(){

   return new ClassA();

   public MyAutoConfig2(){

   System.out.println("constructor MyAutoConfig2");

  }

 

  启动日志如下,

  可以看到实例化了MyAutoConfig2,但是MyAutoConfig确没有,这是因为其类上有@ConditionalOnBean(type = {"com.my.template.config.ClassA"})注解,且在解析MyAutoConfig时并未解析ClassA,把该注解换成@ConditionalOnBean(value= {ClassA.class})看看可以吗

  可以看到还是不行,那么换成@ConditionalOnClass(value={ClassA.class})

  完美解决问题。

    本文主要分析了@ConditionalOnBean注解的使用场景,

    1、该注解的作用时机是在生成bean的时候,确切的说是在解析beanDefinition的时候

    2、该注解可以用在配置类和标识有@Bean的方法上;

    3、三个常用属性value、name、type均有解析顺序的问题;

    4、value、name、type各自的配置方式

  

  本次分享就到这里了,下次,我们@ConditionalOnClass注解见。

  推荐阅读

  深入理解springboot的自动注入

  我的第一个springboot starter

  以上就是springboot的@ConditionalOnBean注解(springboot configuration注解详解)的详细内容,想要了解更多 springboot的@ConditionalOnBean注解的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: