一个接口多个实现?由Spring框架帮你选择

 

一.业务背景

    ToB的产品主要的不确定性来自用户的需求,同样是医院的业务,不同的地区、不同的医院业务流程和需求可能有所不同,比如:上海的医院对医保的校验和北京的医院对医保的校验就有所不同(医保政策不一样)。这就导致在做HIS系统时,需要针对同样的业务要有不同的实现

二.具体实现

    为此,无论是业务还是代码设计都要考虑不同场景不同实现的问题,技术上如何解决?根据医院选择不同的实现。

   上代码。

public class BeanFactoryOperation  implements BeanFactoryPostProcessor,ApplicationContextAware {

    private static Map<String,Class> mapClass = new HashMap<>();

    static{
        mapClass.put("com.mysql.jdbc.Driver",IDaoMysql.class);
        mapClass.put("oracle.jdbc.driver.OracleDriver",IDaoOracle.class);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory)configurableListableBeanFactory;
        String driver = SpringContextUtil.getProperty("spring.datasource.driverClassName");
        Iterator<String> itClass = mapClass.keySet().iterator();
        while(itClass.hasNext()){
            String keyClass = itClass.next();
            if(!keyClass.equals(driver)){//如果不是当前驱动
                Map<String,IDaoBase> map = configurableListableBeanFactory.getBeansOfType(mapClass.get(keyClass));
                Iterator<String> it = map.keySet().iterator();
                while(it.hasNext()){
                    String key = it.next();
                    dlbf.removeBeanDefinition(key);
                    /*boolean b = configurableListableBeanFactory.containsSingleton(key);
                    System.out.println(b);*/
                }
            }
        }
        /**
         * 多实现按医院注入处理
         */
        String globalFlag = SpringContextUtil.getProperty("hospital.flag");

        Map<Class<?>,List<TmpBean>> map = new HashMap<>();
        String[] beanNames = configurableListableBeanFactory.getBeanNamesForType(IHospitalExtensionActionBase.class);
        for(String beanName:beanNames){
            BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(beanName);
            String beanClassName = beanDefinition.getBeanClassName();
            Object o = ReflectUtil.newInstance(beanClassName);
            Class<?> aClass = o.getClass();
            HospitalConditional annotation = aClass.getAnnotation(HospitalConditional.class);
            Map<String, Object> annotationAttributesMap = AnnotationUtils.getAnnotationAttributes(annotation, false);
            String hospitalFlag = (String)annotationAttributesMap.get("hospitalFlag");
            Class inheritClass = (Class)annotationAttributesMap.get("inherit");
            TmpBean tb = new TmpBean();
            tb.setBeanName(beanName);
            tb.setImplFlag(hospitalFlag);
            if(map.containsKey(inheritClass)){
                List<TmpBean> list = map.get(inheritClass);
                list.add(tb);
            }else{
                List<TmpBean> list = new ArrayList<>(5);
                list.add(tb);
                map.put(inheritClass,list);
            }
        }
        Iterator<Class<?>> it = map.keySet().iterator();
        while(it.hasNext()){
            Class<?> clazz = it.next();
            List<TmpBean> tbList = map.get(clazz);
            /**
             * 1.存在当前院区实现
             */
            List<TmpBean> list = tbList.stream().filter(tb -> globalFlag.equals(tb.getImplFlag())).collect(Collectors.toList());
            if(list.size() > 1){
                throw new IllegalStateException("clazz = ["+clazz+"],repeat......");
            }
            if(list.size() == 1){
                List<TmpBean> rmList = tbList.stream().filter(tb -> !globalFlag.equals(tb.getImplFlag())).collect(Collectors.toList());
                rmList.stream().forEach(tb->dlbf.removeBeanDefinition(tb.getBeanName()));
            }
            /**
             * 2.不存在当前院区实现,使用默认实现
             */
            if(list.size() == 0){
                List<TmpBean> defaultList = tbList.stream().filter(tb -> "default".equals(tb.getImplFlag())).collect(Collectors.toList());
                if(defaultList.size() == 1){
                    List<TmpBean> rmList = tbList.stream().filter(tb -> !"default".equals(tb.getImplFlag())).collect(Collectors.toList());
                    rmList.stream().forEach(tb->dlbf.removeBeanDefinition(tb.getBeanName()));
                }
                if(defaultList.size() > 1){
                    throw new IllegalStateException("clazz = ["+clazz+"],repeat......");
                }
                if(defaultList.size() == 0){
                    throw new IllegalStateException("clazz = ["+clazz+"],no default impl......");
                }
            }
        }
        map.clear();

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.setApplicationContext(applicationContext);
    }

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface HospitalConditional {

    String hospitalFlag() default "default";
    /**
     * 上层类或接口
     * @return
     */
    Class<?> inherit() ;

主要就是使用BeanFactoryPostProcessor扩展点,对beanDefinition对象进行指定移除,最后容器在实例化bean时只能找到一个实现类,当然,系统要知道当前是运行在什么环境,这需要配置中心指定环境,根据环境移除不必要的实现,这样在注入接口时Spring IOC中只能找到一个实现类

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hamilton_Huan

原创不易,结合业务原创更不易

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值