Spring Boot 2 实践记录之 条件装配

实验项目是想要使用多种数据库访问方式,比如 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 中,如下代码行:

@Autowired
private 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

时间: 2024-08-30 11:29:18

Spring Boot 2 实践记录之 条件装配的相关文章

spring boot slf4j日记记录配置详解

转 spring boot slf4j日记记录配置详解 2017年12月26日 12:03:34 阅读数:1219 Spring-Boot--日志操作[全局异常捕获消息处理?日志控制台输出+日志文件记录] 最好的演示说明,不是上来就贴配置文件和代码,而是,先来一波配置文件的注释,再来一波代码的测试过程,最后再出个技术在项目中的应用效果,这样的循序渐进的方式,才会让读者更加清楚的理解一项技术是如何运用在项目中的,虽然本篇很简单,几乎不用手写什么代码,但是,比起网上其他人写的同类型的文章来说,我只能

Spring Boot 报错记录

Spring Boot 报错记录 由于新建的项目没有配置数据库连接启动报错,可以通过取消自动数据源自动配置来解决 解决方案1: @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) //@SpringBootApplication @MapperScan("com.example.*") //扫描:该包下相应的class,主要是MyBatis的持久化类. 解决方案2: #去配置文件中配置数据库连接参数 #

Spring Boot 之日志记录

Spring Boot 之日志记录 Spring Boot 支持集成 Java 世界主流的日志库. 如果对于 Java 日志库不熟悉,可以参考:细说 Java 主流日志工具库 关键词: log4j, log4j2, logback, slf4j 日志格式 控制台输出 彩色打印 文件输出 日志级别 日志组 日志配置文件 Spring Boot 中的日志配置 源码 引申和引用 Spring Boot 内部日志全部使用 Commons Logging 记录,但保留底层日志实现.为 Java Util

Spring boot学习(六)Spring boot实现AOP记录操作日志

前言 在实际的项目中,特别是管理系统中,对于那些重要的操作我们通常都会记录操作日志.比如对数据库的CRUD操作,我们都会对每一次重要的操作进行记录,通常的做法是向数据库指定的日志表中插入一条记录.这里就产生了一个问题,难道要我们每次在 CRUD的时候都手动的插入日志记录吗?这肯定是不合适的,这样的操作无疑是加大了开发量,而且不易维护,所以实际项目中总是利用AOP(Aspect Oriented Programming)即面向切面编程这一技术来记录系统中的操作日志. 日志分类 这里我把日志按照面向

Spring Boot @Condition 注解,组合条件你知道吗

上一篇文章 你应该知道的 @ConfigurationProperties 注解的使用姿势,这一篇就够了 介绍了如何通过 @ConfigurationProperties 注解灵活读取配置属性,这篇文章将介绍如何灵活配置 Spring Bean 写在前面 当我们构建一个 Spring 应用的时候,有时我们想在满足指定条件的时候才将某个 bean 加载到应用上下文中, 在Spring 4.0 时代,我们可以通过 @Conditional 注解来实现这类操作 我们看到 @Conditional 注解

【转】Spring Boot @Condition 注解,组合条件你知道吗

原文:https://www.cnblogs.com/FraserYu/p/11280420.html 上一篇文章 你应该知道的 @ConfigurationProperties 注解的使用姿势,这一篇就够了 介绍了如何通过 @ConfigurationProperties 注解灵活读取配置属性,这篇文章将介绍如何灵活配置 Spring Bean 写在前面 当我们构建一个 Spring 应用的时候,有时我们想在满足指定条件的时候才将某个 bean 加载到应用上下文中, 在Spring 4.0 时

Spring Boot 入门实践

一.Eclipse配置Spring Boot环境 1.查看eclipse版本信息: 2.登录:http://spring.io/tools/sts/all 看eclipse对应的插件版本对应的eclipse 信息 很显然我的eclipse版本太低,没有对应的spring boot tools版本,到eclipse官网下载新版本 二.安装spring boot tools 在eclipse中进行插件的安装 1:Help-->Install New Software-->work with 中输入

Spring Boot 最佳实践(一)快速入门

一.关于Spring Boot 在开始了解Spring Boot之前,我们需要先了解一下Spring,因为Spring Boot的诞生和Spring是息息相关的,Spring Boot是Spring发展到一定程度的一个产物,但并不是Spring的替代品,Spring Boot是为了让程序员更好的使用Spring.说到这里可能有些人会迷糊,那到底Spring和Spring Boot有着什么样的联系呢? 1.Spring发展史 在开始之前我们先了解一下Spring,Spring的前身是interfa

spring boot.定时任务问题记录(TaskScheduler/ScheduledExecutorService异常)

一.背景 spring boot的定时任务非常简单,只需要在启动类中加上@EnableScheduling注解,然后在对应的方法上配置@Scheduled就可以了,系统会自动处理并按照Scheduled中的配置定时执行方法. 但是在启动项目的时候,发生了很诡异的现象,有两个TaskScheduler/ScheduledExecutorService的异常打印了出来.但是系统并没有受影响,依然正常启动,而且定时任务也是正常执行. 2018-09-29 15:54:05,187 DEBUG main