SpringBoot的@ConditionalOnMissingBean注解的作用

这篇具有很好参考价值的文章主要介绍了SpringBoot的@ConditionalOnMissingBean注解的作用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、@ConditionalOnMissingBean

@ConditionalOnMissingBean,它是修饰bean的一个注解,主要实现的是,当你的bean被注册之后,如果而注册相同类型的bean,就不会成功,它会保证你的bean只有一个,即你的实例只有一个。

如果不加@ConditionalOnMissingBean,当你注册多个相同的bean时,会出现异常,以此来告诉开发人员。

package ljxwtl.cn.bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author: wtl
 * @License: (C) Copyright 2021, wtl Corporation Limited.
 * @Contact: 1050100468@qq.com
 * @Date: 2021/12/29 10:29 上午
 * @Version: 1.0
 * @Description:
 */
@Configuration
public class UserConfigure {

    @Bean
    public MyTestInjection createBean1(){
        return new MyTestInjection();
    }

    @Bean
    public MyTestInjection createBean2(){
        return new MyTestInjection();
    }
}

这样就会报错!!!

报错信息如下: 

SpringBoot的@ConditionalOnMissingBean注解的作用

当我们把 @ConditionalOnMissingBean放到一个bean注入时,则就不会报错:

package ljxwtl.cn.bean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author: wtl
 * @License: (C) Copyright 2021, wtl Corporation Limited.
 * @Contact: 1050100468@qq.com
 * @Date: 2021/12/29 10:29 上午
 * @Version: 1.0
 * @Description:
 */
@Configuration
public class UserConfigure {

    @Bean
    public MyTestInjection createBean1(){
        return new MyTestInjection();
    }

    @Bean
    @ConditionalOnMissingBean
    public MyTestInjection createBean2(){
        return new MyTestInjection();
    }
}

当我们把 @ConditionalOnMissingBean 去掉之后,你的bean可以注册多次,这时需要用的@Primary来确定你要哪个实现;一般来说,对于自定义的配置类,我们应该加上@ConditionalOnMissingBean注解,以避免多个配置同时注入的风险。

2、@Primary

package ljxwtl.cn.bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @author: wtl
 * @License: (C) Copyright 2021, wtl Corporation Limited.
 * @Contact: 1050100468@qq.com
 * @Version: 1.0
 * @Description:
 */
@Configuration
public class UserConfigure {

    @Bean
    public MyTestInjection createBean1(){
        return new MyTestInjection();
    }

    @Bean
    @Primary
    public MyTestInjection createBean2(){
        return new MyTestInjection();
    }
}

3、@ConditionalOnProperty

通过其三个属性prefix,name以及havingValue来实现的,其中prefix表示配置文件里节点前缀,name用来从application.properties中读取某个属性值,havingValue表示目标值。

  • 如果该值为空,则返回false;
  • 如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。
  • 返回值为false,则该configuration不生效;为true则生效。

下面代码演示为配置文件lind.redis.enable为true时才会注册RedisFactory这个bean:

package ljxwtl.cn.bean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @author: wtl
 * @License: (C) Copyright 2021, wtl Corporation Limited.
 * @Contact: 1050100468@qq.com
 * @Version: 1.0
 * @Description:
 */
@Configuration
@ConditionalOnProperty(prefix="lind.redis",name = "enable", havingValue = "true")
public class UserConfigure {

    @Bean
    public MyTestInjection createBean1(){
        return new MyTestInjection();
    }
}

SpringBoot的@ConditionalOnMissingBean注解的作用

 然后再application.properties里配置:

SpringBoot的@ConditionalOnMissingBean注解的作用这样就成功了!!! 

4、@ConditionalOnBean

@ConditionalOnBean // 当给定的在bean存在时,则实例化当前Bean

@ConditionalOnMissingBean // 当给定的在bean不存在时,则实例化当前Bean 
@ConditionalOnClass // 当给定的类名在类路径上存在,则实例化当前Bean 

@ConditionalOnMissingClass // 当给定的类名在类路径上不存在,则实例化当前Bean

需求场景 :

比如下面一种场景,我在实例化People对象的时候,需要注入一个City对象。这个时候问题来了,如果city没有实例化,那么下面就会报空指针或者直接报错。
所以这里需求很简单,就是当前city存在则实例化people,如果不存在则不实例化people,这个时候@ConditionalOnBean 的作用来了。

package ljxwtl.cn.bean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @author: wtl
 * @License: (C) Copyright 2021, wtl Corporation Limited.
 * @Contact: 1050100468@qq.com
 * @Version: 1.0
 * @Description:
 */
@Configuration
public class UserConfigure {

    @Bean
    @ConditionalOnBean(name = "city")
    public People createPeople(City city){
        System.out.println(city.getCityName());
        return new People();
    }

    @Bean
    public City createCity(){
        City city = new City();
        city.setCityName("北京");
        return city;
    }
}

spring ioc的过程中,优先解析@Component,@Service,@Controller注解的类。其次解析配置类,也就是@Configuration标注的类。最后开始解析配置类中定义的bean

示例代码中people是定义在配置类中的,当执行到配置类解析的时候,@Component,@Service,@Controller ,@Configuration标注的类已经全部被解析,所以这些BeanDifinition已经被同步。

但是bean1的条件注解依赖的是citycity是被定义的配置类中的,因为两个Bean都是配置类中Bean,所以此时配置类的解析无法保证先后顺序,就会出现不生效的情况。

同样的道理,如果依赖的是FeignClient,也有可能会出现不生效的情况。因为FeignClient最终还是由配置类触发,解析的先后顺序也不能保证。

解决

有两种方式:文章来源地址https://www.toymoban.com/news/detail-416187.html

  • 项目中条件注解依赖的类,大多会交给spring容器管理,所以如果要在配置中Bean通过@ConditionalOnBean依赖配置中的Bean时,完全可以用@ConditionalOnClass(Bean2.class)来代替。
  • 如果一定要区分两个配置类的先后顺序,可以将这两个类交与EnableAutoConfiguration管理和触发。也就是定义在META-INF\spring.factories中声明是配置类,然后通过@AutoConfigureBefore、AutoConfigureAfter、AutoConfigureOrder控制先后顺序。因为这三个注解只对自动配置类生效。

到了这里,关于SpringBoot的@ConditionalOnMissingBean注解的作用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java的一些常用注解及其作用

    1.1 @Component 通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。 1.2 @Repository 对应持久层即 Dao 层,主要用于数据库相关操作。 1.3 @Service 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。 1.4 @Controller 对应 Spring MV

    2024年02月01日
    浏览(28)
  • 常用的 Spring Boot 注解及其作用

    Spring Boot 提供了许多注解来简化开发,并帮助开发者在 Spring 应用中实现各种功能。以下是一些常用的 Spring Boot 注解及其作用: @SpringBootApplication : 作用:用于标识主启动类,通常位于 Spring Boot 应用的入口类上。 功能:该注解整合了三个常用注解: @Configuration 、 @EnableAut

    2024年04月25日
    浏览(49)
  • SpringCloud复习:(7)@EnableZuulProxy注解的作用

    使用zuul时,需要加@EnableZuulProxy注解,这个注解定义如下: 可以看到,它引入了一个配置类ZuulProxyMarkerConfiguration,这个类代码如下: 其中定义了一个类型为ZuulProxyMarkerConfiguration.Marker类型的bean. 这个bean将会让ZuulProxyAutoConfiguration自动装配类生效: ZuulProperties类用来对应配置文

    2024年02月08日
    浏览(30)
  • @ConditionalOnMissingBean

    先看下官方解释 从上图主要可以得到如下信息: 仅当BeanFactory中已没有满足指定要求的Bean时才匹配 当放置在@Bean方法上时,Bean类默认为工厂方法的返回类型: 该条件只能匹配到目前为止已由应用程序上下文处理的Bean定义,因此,强烈建议仅在自动配置类上使用该条件。如

    2024年02月08日
    浏览(53)
  • @Transactional注解作用,不生效的场景,事务回滚

    声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。 简而言之,@Transactional注解在代码执行出错的时候能够进行事务的回滚。 在启动类上添加@EnableTransac

    2024年02月10日
    浏览(38)
  • 深入理解Spring @RequestBody注解的用法与作用

    当我们使用 Spring Boot 框架处理客户端提交的 HTTP 请求时,常常需要获取请求参数并将其转换为相应的 Java 对象。@RequestBody 注解可以帮助我们实现这个目标,它用于从 HTTP 请求体中获取请求参数,并将其转换为指定的 Java 对象。本篇博客将介绍 @RequestBody 注解的基本用法和注意

    2024年02月15日
    浏览(36)
  • @Repository注解的作用和用法,以及和@Mapper的区别

    @Repository是属于Spring的注解。它用来标注访问层的类(Dao层),它表示一个仓库,主要用于封装对于数据库的访问。其实现方式与@Component注解相同,只是为了明确类的作用而设立。 即@Repository是@Component注解的一个派生品,与@Service和@Controller都可以理解为@Component注解的扩展。

    2024年02月05日
    浏览(51)
  • Postman 接口传参报错解决与@RequestBody的注解作用记录

    记录接口传参报错与解决和@RequestBody的作用记录 以下面测试代码作为例子:前端发送 POST 请求,请求体里面携带 List 集合的字符串发送给后端接口,后端接口接收到前端发送的请求数据后直接返回给前端。 报错信息: 上面这种写法是 @RequestBody 注解封装 List 对象进行传递的

    2024年02月03日
    浏览(32)
  • MyBatis:生命周期、作用域、结果集映射 ResultMap、日志、分页、使用注解开发、Lombok

    理解不同 作用域 和 生命周期 类别是至关重要的,因为错误的使用会导致非常严重的 并发问题 。 SqlSessionFactoryBuilder 一旦创建了 SqlSessionFactory,就不再需要它了; 最佳作用域 是方法作用域(也就是局部方法变量)。 SqlSessionFactory :相当于 数据库连接池 一旦被创建就应该在

    2024年02月02日
    浏览(44)
  • 【Java】后端开发语言Java和C#,两者对比注解和属性的区别以及作用

    欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《Java》序列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。 温馨提示:博主能力有限,理解水平有限

    2024年01月16日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包