接口存在多个实现类时的动态调用

6 篇文章 0 订阅

版权声明:本文为CSDN博主「EmineWang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a718515028/article/details/72457436

问题的提出

在实际工作中,我们经常会遇到一个接口及多个实现类的情况,并且在不同的条件下会使用不同的实现类。从使用方式上看,有些类似SPI的用法,
但是由于SPI的使用并不是太方便,那么怎么办呢?我们可以借助ApplicationContext的getBeansOfType来实现我们需要的结果。

首先我们看一下这个方法的签名

<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;

从上面的代码上我们可以看出来这个方法能返回一个接口的全部实现类(前提是所有实现类都必须由Spring IoC容器管理)。

org.springframework.beans及org.springframework.context这两个包是Spring IoC容器的基础,
其中重要的类有BeanFactory,BeanFactory是IoC容器的核心接口,其职责包括:实例化、定位、配置应用程序中的
对象及建立这些对象间的依赖关系。

ApplicationContext作为BeanFactory的子类,在Bean管理的功能上得到了很大的增强,也更易于与Spring AOP集成使用。
ApplicationContext的一种实际应用方式。

如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。

实例1

背景:请求参数的检验需要各种规则校验,每个规则都是一个类,需要依次遍历执行。

/**
 * 参数检验工厂类
 * 
 * 如果Bean实现了ApplicationContextAware接口的话,
 * Spring将调用Bean的setApplicationContext()方法,
 * 将bean所在应用上下文引用传入进来。
 */
@Component
public class CheckParamFactory implements ApplicationContextAware {
 
    private static Map<CheckParamCode, CheckParam> checkParamBeanMap ;
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, CheckParam> map = applicationContext.getBeansOfType(CheckParam.class);
        checkParamBeanMap = new HashMap<>();
        map.forEach((key, value) -> checkParamBeanMap .put(value.getCode(), value));
    }
 
    public static <T extends CheckParam> T getCheckParamBean(CheckParamCode code) {
        return (T)checkParamBeanMap.get(code);
    }
 
}

实例2

CheckParam

package com.lhh.myspringboot.interfac;


/**
 * 参数检查接口
 */
public interface CheckParam {

    CheckParamEnum getCode();


    void check();


}

TimeCheck

package com.lhh.myspringboot.interfac;


import org.springframework.stereotype.Component;

/**
 * 时间校验
 */

@Component
public class TimeCheck implements CheckParam{


    @Override
    public CheckParamEnum getCode() {
        return CheckParamEnum.TimeCheck;
    }

    /**
     * 时间校验逻辑
     */
    @Override
    public void check() {

        System.out.println("时间校验");
    }
}

NoneNullCheck

package com.lhh.myspringboot.interfac;


import org.springframework.stereotype.Component;

@Component
public class NoneNullCheck implements CheckParam {
    @Override
    public CheckParamEnum getCode() {
        return CheckParamEnum.NoneNullCheck;
    }

    /**
     * 参数非空校验逻辑
     */
    @Override
    public void check() {

        System.out.println("参数非空校验逻辑");
    }
}

CheckParamEnum

package com.lhh.myspringboot.interfac;

/**
 * 参数检查类型枚举
 */
public enum  CheckParamEnum {


    TimeCheck,
    NoneNullCheck
    //private String code;



}

CheckParamFactory

package com.lhh.myspringboot.interfac;


import com.alibaba.fastjson.JSON;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * 参数检验工厂类
 */

@Component
public class CheckParamFactory  implements ApplicationContextAware {


    public static Map<CheckParamEnum, CheckParam> checkParamBeanMap ;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, CheckParam> map = applicationContext.getBeansOfType(CheckParam.class);
        System.out.println("map:" + JSON.toJSONString(map));
        checkParamBeanMap = new HashMap<>();
        map.forEach((key, value) -> checkParamBeanMap.put(value.getCode(), value));

        System.out.println("checkParamBeanMap:" + JSON.toJSONString(checkParamBeanMap));
    }

    public static <T extends CheckParam> T getCheckParamBean(CheckParamEnum code) {
        return (T)checkParamBeanMap.get(code);
    }


}

CheckParamFactoryTest

package com.lhh.myspringboot.interfac;


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Set;

@RunWith(SpringRunner.class)
@SpringBootTest
public class CheckParamFactoryTest {

    @Test
    public void testCkeck(){

        // 单个调用
        CheckParam checkParamBean = CheckParamFactory.getCheckParamBean(CheckParamEnum.TimeCheck);
        checkParamBean.check();

        // 遍历调用
        Set<CheckParamEnum> checkParamEnums = CheckParamFactory.checkParamBeanMap.keySet();
        checkParamEnums.forEach(i->CheckParamFactory.getCheckParamBean(i).check());

    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值