在Springboot中使用@ConditionalOnMissingBean注解优雅地支持关键业务自定义扩展

文章介绍了如何通过SpringBoot的条件化bean机制来增强插件的灵活性和可扩展性。通过定义接口,提供默认实现,并使用ConditionalOnMissingBean注解,使得用户可以在不修改原有代码的情况下,通过添加自己的实现来覆盖默认行为,达到自定义扩展的目的。
摘要由CSDN通过智能技术生成

目录

背景

思路

示例代码

基本操作

核心功能组件接口

组件的使用者

提供一个默认的实现

运行结果

添加ConditionalOnMissingBean注解

再次运行,还能正常吗?

添加忽略,忽略自己

再次运行

添加自定义实现,看看扩展效果

运行


背景

springboot为我们提供了大量的开箱即用的插件与功能,我们也时常对一些常用功能进行封装,按照springboot的方式提供插件或以其他方式制造我们自己的轮子供自己或团队使用。通常限于我们的设计思路或者在某些方面的取舍,总是不能面面俱到,不能很好的支持一些小众的业务场景,就可以利用spring提供的条件化bean构建机制让我们的插件有很好的自定义扩展能力,能被更多的场景以很小的代价进行应用,从而发挥最大的价值。

思路

把我们的固定逻辑以接口的方式进行定义,当然,也可以用抽象类,但是更推荐使用接口,因为接口可以更加灵活的组合和扩展。然后在我们的核心逻辑中利用多态以接口的方式引入依赖,并执行相应逻辑,可以提供一个针对通用场景的实现作为默认,这样就能使我们的插件能以零代码的方式开箱即用,当需要自定义实现时,则自动关闭默认实现,使用自定义的逻辑。

示例代码

基本操作

核心功能组件接口

package example.component;

public interface ExampleComponent {

	void whoAmI();

}

组件的使用者

package example.component;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Demo implements InitializingBean {

	@Autowired
	private ExampleComponent exampleComponent;

	@Override
	public void afterPropertiesSet() throws Exception {
		exampleComponent.whoAmI();
	}

}

提供一个默认的实现

package example.component;

import org.springframework.stereotype.Component;

@Component
public class DefaultExampleComponent implements ExampleComponent {

	@Override
	public void whoAmI() {
		System.out.println("I'm default.");
	}

}

运行结果

正常输出I'm default.,这个应该没问题好质疑的

添加ConditionalOnMissingBean注解

package example.component;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Component;

@Component
@ConditionalOnMissingBean(value = { ExampleComponent.class })
public class DefaultExampleComponent implements ExampleComponent {

	@Override
	public void whoAmI() {
		System.out.println("I'm default.");
	}

}

再次运行,还能正常吗?

***************************
APPLICATION FAILED TO START
***************************

Description:

Field exampleComponent in example.component.Demo required a bean of type 'example.component.ExampleComponent' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'example.component.ExampleComponent' in your configuration.

把日志级别调到debug,看看到底发生了什么

   DefaultExampleComponent:
      Did not match:
         - @ConditionalOnMissingBean (types: example.component.ExampleComponent; SearchStrategy: all) found beans of type 'example.component.ExampleComponent' defaultExampleComponent (OnBeanCondition)

默认实现也被识别为了该接口的实现,所以不满足条件,没有被创建

添加忽略,忽略自己

package example.component;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Component;

@Component
@ConditionalOnMissingBean(value = { ExampleComponent.class }, ignored = { DefaultExampleComponent.class })
public class DefaultExampleComponent implements ExampleComponent {

	@Override
	public void whoAmI() {
		System.out.println("I'm default.");
	}

}

再次运行

   DefaultExampleComponent matched:
      - @ConditionalOnMissingBean (types: example.component.ExampleComponent ignored: example.component.DefaultExampleComponent; SearchStrategy: all) did not find any beans (OnBeanCondition)

满足条件了,这个bean被创建了

添加自定义实现,看看扩展效果

package example.component;

import org.springframework.stereotype.Component;

@Component
public class AnotherExampleComponent implements ExampleComponent {

	@Override
	public void whoAmI() {
		System.out.println("I'm another.");
	}

}

运行

已经存在一个实现,默认实现不满足条件,没有被创建,使用了自定义的AnotherExampleComponent

   DefaultExampleComponent:
      Did not match:
         - @ConditionalOnMissingBean (types: example.component.ExampleComponent ignored: example.component.DefaultExampleComponent; SearchStrategy: all) found beans of type 'example.component.ExampleComponent' anotherExampleComponent (OnBeanCondition)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringBoot使用@ConditionalOnMissingBean注解可以实现按需自动配置。当原本已经存在的Bean不存在时,该注解才会进行自动配置。 在使用注解时,需要在配置类或者注解类上进行标注。在类上标注时,需要添加@Component注解并指明其扫描路径。然后,使用@ConditionalOnMissingBean注解来判定是否需要自动配置。当原本存在的Bean不存在时,该注解会根据指定的判断条件完成自动配置。 例如,我们需要根据条件来判定是否需要自动配置数据源,可以使用@ConditionalOnMissingBean注解。在使用注解时,我们需要指定检测的bean类型和对应的bean名称,如果检测到该bean不存在,则进行自动配置。具体实现如下: @Configuration public class DataSourceConfig { @Bean(name = "dataSource") @ConditionalOnMissingBean(name = "dataSource") public DataSource dataSource() { // 数据库连接等代码 return dataSource; } } 在该配置类,我们使用@ConditionalOnMissingBean标注了成员函数dataSource(),并且指定了该函数返回的Bean的名称为“dataSource”。当判定不存在该名称的Bean时,就会自动进行配置。 除了根据bean名称判断外,@ConditionalOnMissingBean注解还可以根据Bean类型和条件进行判断。例如,我们需要判断一个接口实现是否存在,可以使用@ConditionalOnMissingBean注解结合@ConditionalOnClass注解进行判定。 @Configuration public class ServiceConfig { @Bean @ConditionalOnMissingBean(IService.class) @ConditionalOnClass(IService.class) public IService iService() { // 接口实现代码 return iService; } } 在该配置类,我们使用@ConditionalOnMissingBean注解结合@ConditionalOnClass注解判断接口实现是否存在。当判定该接口实现不存在时,就会自动进行配置。 总之,@ConditionalOnMissingBean注解为我们带来了更多自动配置的灵活性,可以根据不同的条件进行自动配置,提高了开发效率,减少了代码冗余。它是SpringBoot一个非常实用的注解,开发者可以灵活运用该注解,并根据业务需求进行适当的配置,以满足项目的要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码司机

源于社区,回馈社区,致敬技术

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值