006-Spring Boot自动配置-Condition、Conditional、Spring提供的Conditional自动配置
一、接口Condition、Conditional(原理)
主要提供一下方法
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
true:表示装配
false:表示不装配
1.1、Conditional
在Spring4中引入,其主要作用就是判断条件是否满足,从而决定是否初始化并向容器注册Bean
注解:Conditional() 参数是数组,数组内的都是true才装配
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
/**
* All {@link Condition}s that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();
}
通常配合使用。
示例:
接口:EncodingConvert
package com.lhx.spring.springboot_auto_config;
public interface EncodingConvert {
}
接口实现一:UTF8EncodingConvert
package com.lhx.spring.springboot_auto_config;
public class UTF8EncodingConvert implements EncodingConvert {
}
接口实现二:GBKEncodingConvert
package com.lhx.spring.springboot_auto_config;
public class GBKEncodingConvert implements EncodingConvert {
}
配置类:
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional; @SpringBootConfiguration
public class EncodingConvertConfiguration {
@Bean
public EncodingConvert createGBKEncodingConvert() {
return new GBKEncodingConvert();
} @Bean
public EncodingConvert createUTF8EncodingConvert() {
return new UTF8EncodingConvert();
}
}
App:
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.Conditional; @SpringBootApplication
public class App {
@Bean
public Runnable createRunnable() {
return () -> {
System.out.println("spring boot is running");
};
} public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
context.getBean(Runnable.class).run();
//可以通过启动参数修改-Dfile.encoding=GBK
System.out.println(System.getProperty("file.encoding"));
System.out.println(context.getBeansOfType(EncodingConvert.class));
context.close();
}
}
此时,会发现连个接口实现都会被装配进来。
UTF8Condition实现Condition接口
package com.lhx.spring.springboot_auto_config; import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; 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".equalsIgnoreCase(encoding);
}
return false;
} }
GBKCondition实现Condition接口
package com.lhx.spring.springboot_auto_config; import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; public class GBKCondition implements Condition { @Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String encoding = System.getProperty("file.encoding");
if (encoding != null) {
return "gbk".equalsIgnoreCase(encoding);
}
return false;
} }
修改配置类
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional; @SpringBootConfiguration
public class EncodingConvertConfiguration {
@Bean
@Conditional(GBKCondition.class)
public EncodingConvert createGBKEncodingConvert() {
return new GBKEncodingConvert();
} @Bean
@Conditional(UTF8Condition.class)
public EncodingConvert createUTF8EncodingConvert() {
return new UTF8EncodingConvert();
}
}
此时,会发现会根据file.encoding值来装配接口类。
可在启动参数增加
-Dfile.encoding=GBK

然后调试,发现装配类也变了
注意:@Conditional也可以作用在类上
二、Spring提供的Conditional自动配置
jar:spring-boot-autoconfigure中,org.springframework.boot.autoconfigure.condition;即spring-boot提供
ConditionalOnBean:当存在某个bean时候装配
ConditionalOnMissingBean:当不存在某个bean时候装配注解的bean
ConditionalOnClass:当classpath有才装配
ConditionalOnExpression:
ConditionalOnJava:JDK版本符合时候才装配
ConditionalOnNotWebApplication:不是web环境才装配
ConditionalOnWebApplication:是web环境才装配
ConditionalOnResource:资源存在才装配
ConditionalOnProperty:配置存在才装配
2.1、ConditionalOnProperty 配置存在匹配时候才配置
增加配置类
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; @SpringBootConfiguration
public class UserConfiguration { @Bean
@ConditionalOnProperty(name = "runnable.enable", havingValue = "true")
public Runnable createRunnable() {
return () -> {
};
} }
App2编写
package com.lhx.spring.springboot_auto_config; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.Conditional; @SpringBootApplication
public class App2 { public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(App2.class, args);
System.out.println(context.getBeansOfType(Runnable.class));
context.close();
}
}
默认是不能装配的
可以再application.properties中添加runnable.enable=true即可装配
或者@ConditionalOnProperty(name = "runnable.enable", havingValue = "true")增加
matchIfMissing=true,表示配置没有的时候也生效
2.2、ConditionalOnClass classpath 有某个类才装配
增加或删除maven,查看效果
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
使用代码
@Bean
@ConditionalOnClass(name="com.google.gson.Gson")
public Runnable createGsonRunnable() {
return () -> {
};
}
2.3、ConditionalOnBean:根据容器中是否存在某个Bean进行装配
@Bean
@ConditionalOnBean(name="user")
public Runnable createOnBeanRunnable() {
return () -> {
};
}
示例一、根据配置选择不同的实现类注入
需求:根据配置选择不同的实现类注入,有个业务逻辑,有两套模式,大部分功能流程一致,但涉及某些实现不一致,标准的模板模式:004-行为型-02-模板方法模式(Template Method)
实际使用中会有,默认是一种实现,如果有某个配置,则生效。可以参看springboot自动装配实现,如Cache等
实现:https://github.com/bjlhx15/common.git spring-framework-core/spring-aop/testconditional
基础业务接口
public interface ITestConditionalService {
String getBefore();
String get();
}
如果新增业务需要新增配置
public class ConstBean {
public final static String atest="atest";
public final static String btest="btest";
}
抽象类实现公共方案步骤
public abstract class AbstractTestConditionalService implements ITestConditionalService {
@Override
public abstract String getBefore();
@Override
public String get() {
String before = this.getBefore();
// do something
return "before:" + before;
}
}
第一种实现方案:也就是默认方案
@Service("aTestConditionalServiceImpl")
@ConditionalOnProperty(name = "set.test",havingValue = ConstBean.atest,matchIfMissing = true)
public class ATestConditionalServiceImpl extends AbstractTestConditionalService {
@Override
public String getBefore() {
return "atest test";
}
}
第二种方案
@Service("bTestConditionalServiceImpl")
@ConditionalOnProperty(name = "set.test",havingValue = ConstBean.btest)
public class BTestConditionalServiceImpl extends AbstractTestConditionalService {
@Override
public String getBefore() {
return "btest test";
}
}
配置 如果是a逻辑可默认不写
# 配置实现 atest、btest
set.test=atest
006-Spring Boot自动配置-Condition、Conditional、Spring提供的Conditional自动配置的更多相关文章
- Spring Boot 揭秘与实战 自己实现一个简单的自动配置模块
文章目录 1. 实战的开端 – Maven搭建 2. 参数的配置 - 属性参数类 3. 真的很简单 - 简单的服务类 4. 自动配置的核心 - 自动配置类 5. spring.factories 不要 ...
- 峰哥说技术:06-手撸Spring Boot自定义启动器,解密Spring Boot自动化配置原理
Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 06 峰哥说技术:手撸Spring Boot自定义启动器,解密Spring Boot自动化配置原理 Sp ...
- Spring Boot干货系列:(七)默认日志框架配置
Spring Boot干货系列:(七)默认日志框架配置 原创 2017-04-05 嘟嘟MD 嘟爷java超神学堂 前言 今天来介绍下Spring Boot如何配置日志logback,我刚学习的时候, ...
- Spring Boot 项目学习 (二) MySql + MyBatis 注解 + 分页控件 配置
0 引言 本文主要在Spring Boot 基础项目的基础上,添加 Mysql .MyBatis(注解方式)与 分页控件 的配置,用于协助完成数据库操作. 1 创建数据表 这个过程就暂时省略了. 2 ...
- Spring Boot 2.X(四):Spring Boot 自定义 Web MVC 配置
0.准备 Spring Boot 不仅提供了相当简单使用的自动配置功能,而且开放了非常自由灵活的配置类.Spring MVC 为我们提供了 WebMvcConfigurationSupport 类和一 ...
- Spring Boot 框架下使用MyBatis访问数据库之基于XML配置的方式
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...
- spring boot系列(五)spring boot 配置spring data jpa (查询方法)
接着上面spring boot系列(四)spring boot 配置spring data jpa 保存修改方法继续做查询的测试: 1 创建UserInfo实体类,代码和https://www.cnb ...
- Spring Boot 揭秘与实战 附录 - Spring Boot 公共配置
Spring Boot 公共配置,配置 application.properties/application.yml 文件中. 摘自:http://docs.spring.io/spring-boot ...
- Spring Boot教程(三十八)使用MyBatis注解配置详解(1)
之前在Spring Boot中整合MyBatis时,采用了注解的配置方式,相信很多人还是比较喜欢这种优雅的方式的,也收到不少读者朋友的反馈和问题,主要集中于针对各种场景下注解如何使用,下面就对几种常见 ...
- 【转】Spring Boot 构建应用——快速构建 Spring Boot 应用
Spring Boot 简化了 Spring 应用开发,不需要配置就能运行 Spring 应用,Spring Boot 的自动配置是通过 Spring 4.x 的条件注解 @Conditional 来 ...
随机推荐
- react-native样式引入
react-native 第一种:在标签内部使用样式 import React from 'react'; class Demo extends React.Component{ render(){ ...
- vue 使用element-ui中的Notification自定义按钮并实现关闭功能以及如何处理多个通知
使用element-ui中的Notification,只有一个message属性是有很大的操作空间,其余的都是写死的,无法进行扩展,达不到想要的效果.所以只能在message上下功夫. 在elemen ...
- Foundation框架下的常用类(NSNumber, NSValue, NSDate,NSDateFormatter)
1.NSNumber 将基础数类型数据转成对象数据(比如int float double BOOL long等等) //通过NSNumber将基础数类型数据转成对象数据. NSNumber * i ...
- 管线命令(Pipe)
管线命令接受|前面传来的stdout,管线示意图如下所示: 管线两个需要注意的地方: 1.管线仅会处理stdout,忽略对stderr的处理 2.管线必须接受前个指令的stdin才是 那么,如果我想接 ...
- Keepalived高可用服务器案例
部署Keepalived高可用软件,实现如下: - 使用Keepalived实现web服务器的高可用 - Web服务器IP地址分别为192.168.4.100和192.168.4.200 - Web服 ...
- 洛谷 P2622 关灯问题II (状态压缩+BFS)
题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯--按下了第i个按钮,对于所有的灯都有一个效果.按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时 ...
- 小程序makePhoneCall拨打电话问题
调用wx.makePhoneCall后肯定会弹出一个询问框,此时无论是点击确认或者取消,页面都会依次触发app.js中的onHide函数和onShow函数,所以需要注意
- 【u-boot-2018.05】make配置过程分析
https://blog.csdn.net/q_z_r_s/article/details/80718518 从u-boot-2014.10版本引入Kbuild系统之后,Makefile的管理和组织跟 ...
- 关于在IOS中 contenteditable=true 无法输入的问题
解决: 1.添加样式-webkit-user-select:text 2.如果引入了fastclick,需要添加个类名 needsclick 来源于知乎(https://www.zhihu.com/q ...
- pycharm快捷键的使用、内存管理、变量、数据类型、注释相关笔记
目录 pycharm快捷键的使用 变量 python内存管理 小整数池 引用计数 垃圾回收机制 循环引用 变量的三种打印形式 数字类型 字符串 注释 pycharm快捷键的使用 ctrl+c复制,默认 ...