博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Boot 2 实践记录之 条件装配
阅读量:4308 次
发布时间:2019-06-06

本文共 2947 字,大约阅读时间需要 9 分钟。

实验项目是想要使用多种数据库访问方式,比如 JPA 和 MyBatis。

项目的 Service 层业务逻辑相同,只是具体实现代码不同,自然是一组接口,两组实现类的架构比较合理。

不过这种模式却有一个问题,如果 Bean 是按实现类装配,则在切换数据库访问方式时,就需要大量的代码修改。如果按接口装配,则会出现歧义(同一接口有两个实现,无法自动装配)。

虽然可以使用「首选Bean」或「限定」装配,但是与直接使用实现类装配一样,切换数据库访问地,仍然要大量修改源码。

经过实验,使用「条件装配」实现了利用配置切换数据库访问方式,不需要修改代码了。

示例:

先定义 Service 接口:

public interface UserServiceInterface {    ......  }

再定义 MyBatis 实现类:

@Service@Conditional(MybatisCondition.class)public class UserServiceMybatisImpl implements UserServiceInterface {    ......}

注意其中的 @Conditional(MybatisCondition.class),MybatisCondition 类必须实现 org.springframework.context.annotation.Condition 接口,该接口仅有一个 matches 方法,当该方法返回真时,UserServiceMybatisImpl 被装配。

MybatisCondition 的 matches 方法的逻辑被实现为根据配置文件中的 use.data.access.method 属性是否为 mybatis,来决定是否装配 UserServiceMybatisImpl 类:

import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.env.Environment;import org.springframework.core.type.AnnotatedTypeMetadata;public class MybatisCondition implements Condition {    @Override    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        Environment env = context.getEnvironment();        if (env.getProperty("use.data.access.method").equals("mybatis")) {            return true;        }        return false;    }}

再定义 SPA 实现类及其 SpaCondition 类,实现方式与 Mybatis 相同,仅在配置项为 spa 时,装配 UserServiceSpaImpl 类:

@Service@Conditional(SpaCondition.class)public class UserServiceSpaImpl implements UserServiceInterface {    ......}
import org.springframework.context.annotation.Condition;import org.springframework.context.annotation.ConditionContext;import org.springframework.core.env.Environment;import org.springframework.core.type.AnnotatedTypeMetadata;public class SpaCondition implements Condition {    @Override    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {        Environment env = context.getEnvironment();        if (env.getProperty("use.data.access.method").equals("spa")) {            return true;        }        return false;    }}

定义一个类,自动装配 UserServiceInterface,并打印其类名:

public class Test {    @Autowired    private UserServiceInterface userServiceInterface;        public void testUserService() {        System.out.println(userServiceInterface.getClass();    }}

现在还不能运行,需要添加配置项。

先将配置项配置为 mybatis:

use.data.access.method = mybatis

运行 Test 类的 testUserService 方法,结果为:

UserServiceMybatisImpl

将配置项修改为 spa:

use.data.access.method = spa

运行 Test 类的 testUserService 方法,结果为:

UserServiceSpaImpl

 

不过,有个小小的缺憾,就是在 Idea 中,如下代码行:

@Autowiredprivate UserServiceInterface userServiceInterface;

会有错误提示:

Could not autowire. There is more than one bean of 'UserServiceInterface' type.Beans:userServiceMybatisImpl   (UserServiceMybatisImpl.java) userServiceSpaImpl   (UserServiceSpaImpl.java)

由于配置项是在运行时读取的,Idea 在静态语法检查时,实在没办法搞定这个自动装配的判断。

没关系,不影响运行!

转载于:https://www.cnblogs.com/matchless/p/10389918.html

你可能感兴趣的文章
设计模式06_原型
查看>>
设计模式07_建造者
查看>>
设计模式08_适配器
查看>>
设计模式09_代理模式
查看>>
设计模式10_桥接
查看>>
设计模式11_装饰器
查看>>
设计模式12_外观模式
查看>>
设计模式13_享元模式
查看>>
设计模式14_组合结构
查看>>
设计模式15_模板
查看>>
海龟交易法则01_玩风险的交易者
查看>>
CTA策略02_boll
查看>>
vnpy通过jqdatasdk初始化实时数据及历史数据下载
查看>>
设计模式19_状态
查看>>
设计模式20_观察者
查看>>
vnpy学习10_常见坑02
查看>>
用时三个月,终于把所有的Python库全部整理了!拿去别客气!
查看>>
pd.stats.ols.MovingOLS以及替代
查看>>
vnpy学习11_增加测试评估指标
查看>>
资金流入流出计算方法
查看>>