为网站做一则广告语/网站排名英文
在原生java中就有spi来为我们接口作扩展通过配置文件去指定实现类来灵活编码,而不乏很多开源框架对java的spi 作了增强,比如dubbo。具体duboo的spi增强了什么大家可以去dubbo官网参考这里不作展开说明
来说说我们今天的目标:
需求: 因为我们项目可能需要切换数据库,但是为了平滑切换,准备了这两个数据源Mapper,希望有什么问题可以通过配置文件马上回滚到原先的数据源。比如原先的mapper是查询的mysql,新的数据源是查询的postgresql。我们想先切换为postgresql去做改动验证,如果有问题可以马上通过配置文件切换为mysql。
传统的java spi可以通过配置文件制定接口的实现类,但是我们的接口实现类是Mybatis的Mapper,由Mybatis动态代理生成的。没法直接指定,但是我们可以基于SpringB的@ConditionalOnProperty来实现我们想要的效果
@ConditionalOnProperty
@ConditionalOnProperty的作用很明确,通过条件来判断Configuration是否生效
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {String[] value() default {}; //property名称的前缀String prefix() default "";//数组,property完整名称或部分名称(可与prefix组合使用,组成完整的property名称),与value不可同时使用 String[] name() default {};//与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置 String havingValue() default "";//缺少该property时是否可以加载。如果为true,没有该property也会正常加载,反之则不会生效boolean matchIfMissing() default false;/ boolean relaxedNames() default true;
}
}
看上面的解释有点懵,一般使用下面三个属性
- prefix
- name
- havingValue
来通过一个具体例子看看吧
上面的需求说的很清楚,我们需要通过配置文件是加载Server的实现pg实现还是mysql实现。对于Service在Spring中如果有两个实现类是一个list,否则会报错,所以我们只能加载一个实现类
Server接口定义:
public interface OrderManager {int insert(@Param("orders") List<Order> orders);
}
两个不同的实现类
- PGOrderManagerImpl
@Service
@Configuration
@ConditionalOnProperty(prefix = "order-detail", name = "impl", havingValue = "mysql")
public class PGOrderManagerImpl implements OrderManager{@AutowiredOrderMapper orderMapper;@Overridepublic int insert(List<Order> orders) {return orderMapper.insert(orders);}}
- MySqlOrderManagerImpl
@Service
@Configuration
@ConditionalOnProperty(prefix = "order-detail", name = "impl", havingValue = "pg")
public class MySqlOrderManagerImpl implements OrderManager{@AutowiredMySqlOrderMapper mySqlOrderMapper;@Overridepublic int insert(List<Order> orders) {return orderMapper.insert(orders);}}
配置文件:
order-detail.impl = pg
这样我们只需要修改配置文件是pg 还是mysql就可以指定不同的接口实现类了,是不是很方便,需要注意的是可能idea在编码的时候会给你提示OrderManager 有两个实现类报错,不过不影响
关于我
觉得文章不错请扫码关注我吧