Spring Boot中选择性加载Bean的几种方式

说明:用过Spring框架的都知道其自动装配的特性,本文介绍几种选择性加载Bean的方式。Spring自动装配参考以下两篇文章:

@ConditionalOnProperty

@ConditionalOnProperty,根据配置文件中指定的值决定是否加载,如下:

java 复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

/**
 * 根据配置文件中指定的值决定是否加载;
 */
@Component
@ConditionalOnProperty(name = "dev.name", havingValue = "hezy", matchIfMissing = true)
public class OnProperty {
}

参数,其中:

  • name/value:配置项名称;

  • havingValue:配置值;

  • matchIfMissing:表示不存在该配置项时,是否加载Bean,默认false,需要注意,这里说的是没有该配置项,而不是配置值对应不上;


如上面的代码,表示配置文件中存在dev.name配置项,且值为hezy时加载Bean,没有配置项的话加载;

application.yml,如下:

yml 复制代码
server:
  port: 7084

dev:
  name: "dev"

启动项目,不加载该Bean,因为配置项的值对不上

@ConditionalOnJava

@ConditionalOnJava,根据Java版本决定是否加载,如下:

java 复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava;
import org.springframework.boot.system.JavaVersion;
import org.springframework.stereotype.Component;

/**
 * 根据Java版本决定是否加载
 */
@Component
@ConditionalOnJava(JavaVersion.SEVENTEEN)
public class OnJava {
}

注解的参数只有一个,即Java版本,如我IDEA中加载的JDK11,填JavaVersion.SEVENTEEN,Java17,不会加载该Bean。但是如果设置的是JavaVersion.EIGHT,则会加载Bean,也就说这里向下兼容了。

(Java11)

(代码设置的Java8)

java 复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava;
import org.springframework.boot.system.JavaVersion;
import org.springframework.stereotype.Component;

/**
 * 根据Java版本决定是否加载
 */
@Component
@ConditionalOnJava(JavaVersion.EIGHT)
public class OnJava {
}

启动项目,加载了Bean

@ConditionalOnBean

@ConditionalOnBean,根据Spring容器中是否存在指定的Bean决定是否加载。有以下三种配置:

  • 指定类:@ConditionalOnBean(OnJava.class)

  • 指定Bean:@ConditionalOnBean(name = "onProperty")

  • 指定多个类:@ConditionalOnBean({OnProperty.class, OnJava.class})

如下,表示只有容器中存在OnJava.class的Bean时才加载

java 复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;

/**
 * 根据Spring容器中是否存在指定的Bean决定是否加载
 */
@Component
@ConditionalOnBean(OnJava.class)
public class OnBean {
}

因为容器中有OnJava,所以OnBean也加载了;

@ConditionalOnMissingBean

@ConditionalOnMissingBean,根据Spring容器中是否不存在指定的Bean决定是否加载,与@ConditionalOnBean相反。也有以下三种配置方式:

  • 指定类:@ConditionalOnMissingBean(OnJava.class)

  • 指定Bean:@ConditionalOnMissingBean(name = "onProperty")

  • 指定多个类:@ConditionalOnMissingBean({OnProperty.class, OnJava.class})

如下,表示容器中OnJava、OnClass都不存在时才加载。注意如果指定多个类,它们的条件是 And 的关系,@ConditionalOnBean 也一样。

java 复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Component;

/**
 * 根据Spring容器中是否不存在指定的Bean决定是否加载
 */
@Component
@ConditionalOnMissingBean({OnJava.class, OnProperty.class})
public class OnMissingBean {
}

如下,容器中没有OnProperty,但是OnJava有,所以OnMissingBean也不加载,需要都不存在才加载

@ConditionalOnClass

@ConditionalOnClass,根据类是否存在指定的类来决定是否加载,有以下三种配置:

  • 指定类:@ConditionalOnClass(OnJava.class);

  • 指定类的全限定类名:@ConditionalOnClass(name = "com.hezy.bean.OnJava")

  • 指定多个类:@ConditionalOnClass({OnJava.class, OnClass.class})

需要和上面的指定OnBean区分开,指定Bean是需要类加载到容器里,即类上要打@Component、@Service、@Controller等这样的注解,而OnClass就不用,只要你存在这样的类文件即可。

如下,表示存在OnJava类加载

java 复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;

/**
 * 根据类是否存在指定的类来决定是否加载
 */
@Component
@ConditionalOnClass(name = "com.hezy.bean.OnJava")
public class OnClass {
}

把OnJava类上的@Component注解去掉,启动项目

java 复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava;
import org.springframework.boot.system.JavaVersion;

/**
 * 根据Java版本决定是否加载
 */
@ConditionalOnJava(JavaVersion.EIGHT)
public class OnJava {
}

可以看到,容器里没有OnJava的Bean,但是OnClass加载了

@ConditionalOnMissingClass

@ConditionalOnMissingClass,根据类路径中是否不存在指定的类来决定是否加载,与@ConditionalOnClass相反,配置方式有两种:

  • 指定类的全限定类名:@ConditionalOnMissingClass("com.hezy.bean.OnJava")

  • 指定多个类:@ConditionalOnMissingClass({"com.hezy.bean.OnJava1", "com.hezy.bean.OnJava2"})

为什么少了指定类,因为这里配置的是不存在的类,不存在的类,怎么写 类名.class (笑)

如下,表示不存在对应路径的OnJava1、OnJava2时才加载,配置多个类,是And的关系,即需要都不存在才加载;

java 复制代码
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.stereotype.Component;

/**
 * 根据类路径中是否不存在指定的类来决定是否加载
 */
@Component
@ConditionalOnMissingClass({"com.hezy.bean.OnJava1", "com.hezy.bean.OnJava2"})
public class OnMissingClass {
}

因为配置的类都不存在,所以加载了OnMissingClass

总结

本文介绍了Spring Boot中六种选择性加载Bean的方式,按照配置文件加载Bean的方式用的最多。除此六种,Spring还支持其他方式,可在Spring Boot框架中用 @Conditional 为前缀搜索,如下:

相关推荐
Wang's Blog40 分钟前
Java 项目实战: 交友项目 - 项目:需求分析与滑动数据设计
java·开发语言·交友
前端 贾公子1 小时前
第 5 章:Codex 从可运行程序到可交付工具
java·前端·数据库
CoderYanger1 小时前
Java EE 进阶:5. Spring IoC&DI(第三弹):Spring DI
java·开发语言·spring boot·spring·面试·java-ee·mvc
Thneonl1 小时前
Claude Code 频繁 Compacting?发布次日我根治了 2 个痛点
后端·rust
一条泥憨鱼2 小时前
【Kafka】零基础学习教程
java·分布式·学习·kafka
Wang's Blog2 小时前
Java 项目实战:交友项目 - 即时通信总结:全链路复盘、可复用清单与自检
java·python·交友
文丑颜不良啊2 小时前
LeetCode1501~1520题目解析
java·leetcode
长不大的杨瑞杰2 小时前
OpenCode v2 LSP 实战:内置语言服务器、自定义配置与诊断闭环
java·人工智能·typescript·lsp·opencode
云和数据.ChenGuang2 小时前
python和java的try
java·开发语言·python
日日大王学编程2 小时前
阿里巴巴开源 Data Agent(Text2SQL)项目全维度详解
java·ai·开源