0
点赞
收藏
分享

微信扫一扫

springboot原理实战(7)--使用Conditional实现按条件注入bean


文章目录

  • ​​目录​​
  • ​​一、Conditional按照条件注入bean原理​​
  • ​​二、自定义condition接口注入bean​​
  • ​​三、springboot提供的@Conditional工具类​​
  • ​​1.@ConditionalOnProperty​​
  • ​​2.@ConditionalOnClass​​
  • ​​3.@ConditionalOnBean​​

目录

本系列博客第一篇就是如何利用spring4+注解方式注入bean,在springboot中提供了按照条件方式注入,我们可以按照条件选择注入或者不注入bean。

本篇博客的内容概要:

springboot原理实战(7)--使用Conditional实现按条件注入bean_工具类

一、Conditional按照条件注入bean原理

看下Conditional注解源码,它有个value属性类型就是condition的。

springboot原理实战(7)--使用Conditional实现按条件注入bean_自定义_02


看下Condition接口源码:

springboot原理实战(7)--使用Conditional实现按条件注入bean_自定义_03


这个接口只有一个方法,是否匹配的matches方法,返回boolean类型。

所以​​Conditional注解 能够提供基于条件的自动配置,一般配合Condition接口(1个或多个)一起使用,只有接口的实现类都返回true,才装配,否则不装配.​​​。
现在我们自定义一个condition实现类来,结合conditional注解,来切换是否能注入bean。

二、自定义condition接口注入bean

案例:根据代码的字符集。 判断是否注入我们自己定义的bean。
字符集转换接口:

public interface EncodingConvert {
}

有2个实现类:

public class GbkEncodinConvert implements EncodingConvert{
}

public class Utf8EncodingConvert implements EncodingConvert {
}

然后分别写2个condition条件,来切换是否能注入bean的实现类:

public class GbkCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String encoding = System.getProperty("file.encoding");
if (encoding != null){
return "gbk".equals(encoding.toLowerCase());
}
return false;
}
}

public class Utf8Condition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String encoding = System.getProperty("file.encoding");
if (encoding != null){
return "utf-8".equals(encoding.toLowerCase());
}
return false;
}
}

写个配置类,在配置类里装载bean:

@SpringBootConfiguration
public class EncodingConvertConfiguration {

@Bean
@Conditional(Utf8Condition.class)
public EncodingConvert createUtf8EncodingConvert(){
return new Utf8EncodingConvert();
}

@Bean
@Conditional(GbkCondition.class)
public EncodingConvert createGbkEncodinConvert(){
return new GbkEncodinConvert();
}
}

可以看到上面的装载方式都加了个条件,@Conditional,参数内容为
根据​​​System.getProperty("file.encoding")​​的值来判断,是否装载,如果是utf-8就装载createUtf8EncodingConvert类,如果是gbk就装载createGbkEncodinConvert这个类。

我们进入入口函数测试下:

@SpringBootApplication
public class Demo4Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Demo4Application.class, args);
System.out.println(System.getProperty("file.encoding"));
System.out.println(context.getBeansOfType(EncodingConvert.class));
context.close();
}
}

打印结果:

springboot原理实战(7)--使用Conditional实现按条件注入bean_工具类_04


显示注入了bean,因为编码字符集是UTF-8。

我们切换下参数:再试下:

springboot原理实战(7)--使用Conditional实现按条件注入bean_spring_05


打印结果:

springboot原理实战(7)--使用Conditional实现按条件注入bean_自定义_06


同时我们也可以将@Conditional条件放在类上,因为@Conditional的value是个集合,所以可以指定多个,这些条件都满足才能装载类里面的bean:

@SpringBootConfiguration
@Conditional({Utf8Condition.class,GbkCondition.class})
public class EncodingConvertConfiguration {

@Bean
public EncodingConvert createUtf8EncodingConvert(){
return new Utf8EncodingConvert();
}

@Bean
public EncodingConvert createGbkEncodinConvert(){
return new GbkEncodinConvert();
}
}

打印结果,因为类的条件为false,所以没有装载bean。

springboot原理实战(7)--使用Conditional实现按条件注入bean_spring boot_07


我们改成类的条件为true的情况:

@SpringBootConfiguration
@Conditional({Utf8Condition.class})
public class EncodingConvertConfiguration {

@Bean
public EncodingConvert createUtf8EncodingConvert(){
return new Utf8EncodingConvert();
}

@Bean
public EncodingConvert createGbkEncodinConvert(){
return new GbkEncodinConvert();
}
}

再次运行入口函数,发现类下的2个bean都被注入了:

springboot原理实战(7)--使用Conditional实现按条件注入bean_spring boot_08

三、springboot提供的@Conditional工具类

上面是我们自己定义的@Conditional参数中的condition实现类,其实springboot也提供了很多的实用的@Conditional工具类,我们可以直接去使用就可以。


springboot原理实战(7)--使用Conditional实现按条件注入bean_spring_09


里面有很多的condition实现类:

注解

说明

​@ConditionalOnSingleCandidate​

当给定类型的bean存在并且指定为Primary的给定类型存在时,返回true

​@ConditionalOnMissingBean​

当给定的类型、类名、注解、昵称在beanFactory中不存在时返回true.各类型间是or的关系

​@ConditionalOnBean​

与上面相反,要求bean存在

​@ConditionalOnMissingClass​

当给定的类名在类路径上不存在时返回true,各类型间是and的关系

​@ConditionalOnClass​

与上面相反,要求类存在

​@ConditionalOnCloudPlatform​

当所配置的CloudPlatform为激活时返回true

​@ConditionalOnExpression​

spel表达式执行为true

​@ConditionalOnJava​

运行时的java版本号是否包含给定的版本号.如果包含,返回匹配,否则,返回不匹配

​@ConditionalOnProperty​

要求配置属性匹配条件

​@ConditionalOnJndi​

给定的jndi的Location 必须存在一个.否则,返回不匹配

​@ConditionalOnNotWebApplication​

web环境不存在时

​@ConditionalOnWebApplication​

web环境存在时

​@ConditionalOnResource​

要求制定的资源存在

现在我们使用几个测试下

1.@ConditionalOnProperty

某个属性等于某个值的时候才装配。

@SpringBootConfiguration
public class UserConfiguration {

//某个属性等于某个值的时候才装配
@Bean
@ConditionalOnProperty(name="runable.enabled",havingValue = "true")
public Runnable createRunable(){
return () -> {};
}
}

这个例子是 如果有runable.enabled这个属性,并且值为true就注入,我们测试下:

@SpringBootApplication
public class Demo4Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Demo4Application.class, args);
System.out.println(context.getBeansOfType(Runnable.class));
context.close();
}
}

运行结果:显示没有装载。

springboot原理实战(7)--使用Conditional实现按条件注入bean_工具类_10


我们在application.properties添加​​runable.enabled=true​

runable.enabled=true

再次测试,显示已经装载进来了:

springboot原理实战(7)--使用Conditional实现按条件注入bean_工具类_11


@ConditionalOnProperty还有个属性​​matchIfMissing​​,没有这个属性的时候,让条件变为true或false。

我们做个测试,让其他变为true,同时删除配置文件中的​​runable.enabled=false​​这行代码:

@SpringBootConfiguration
public class UserConfiguration {

//某个属性等于某个值得时候才装配
@Bean
@ConditionalOnProperty(name="runable.enabled",havingValue = "true",matchIfMissing = true)
public Runnable createRunable(){
return () -> {};
}
}

测试下,在缺少配置文件属性的情况下也注入进来了:

springboot原理实战(7)--使用Conditional实现按条件注入bean_工具类_12

2.@ConditionalOnClass

@SpringBootConfiguration
public class UserConfiguration {


//表示 classpath中存在某个class的时候才装配
@Bean
@ConditionalOnClass(name="com.google.gson.Gson")
public Runnable createGsonRunable(){
return () -> {};
}
}

我们判断如果项目有这个Gson类就加载否则不加载,现在项目jar里面没有的,应该不注入,我们看下效果:

@SpringBootApplication
public class Demo4Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Demo4Application.class, args);
System.out.println(context.getBeansOfType(Runnable.class));
context.close();
}
}

运行结果:的确没注入进来。

springboot原理实战(7)--使用Conditional实现按条件注入bean_自定义_13


现在我们让他注入进来,在pom.xml中引入gson包

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>

再次运行,显示已经注入进来了:

springboot原理实战(7)--使用Conditional实现按条件注入bean_自定义_14

3.@ConditionalOnBean

​根据容器中是否存在某个bean来进行装配​

@SpringBootConfiguration
public class UserConfiguration {
//根据容器中是否存在某个bean来进行装配
@Bean
@ConditionalOnBean(name="user")
public Runnable createUserRunable(){
return () -> {};
}
}

目前项目中没有名字为user的bean,我们打印测试下:

springboot原理实战(7)--使用Conditional实现按条件注入bean_工具类_15


的确没注入。

我们写个user的bean:

@Component
public class User {
}

再次测试,显示注入了。

springboot原理实战(7)--使用Conditional实现按条件注入bean_spring boot_16


本文的所有内容已经完毕,主要就是按照条件转载bean,可以自定义和使用springboot提供的一些实用的工具类来为我所用。在以后的工作中,具体的类再具体了解吧。

个人微信公号:

搜索: 怒放de每一天

不定时推送相关文章,期待和大家一起成长!!

springboot原理实战(7)--使用Conditional实现按条件注入bean_spring boot_17


举报

相关推荐

0 条评论