使用Spring功能来实现多个接口类的动态调用

电脑杂谈  发布时间:2020-05-17 19:08:49  来源:网络整理

常用类之tcp连接类s_spring常用的接口和类_spring常用工具类

背景

这两个包org.springframework.beans和org.springframework.context是Spring IoC容器的基础,

重要的类之一是BeanFactory,它是IoC容器的核心接口. 它的职责包括: 实例化,定位和配置应用程序

对象并在这些对象之间建立依赖关系.

ApplicationContext作为BeanFactory的子类,在Bean管理功能上得到了极大的增强,并且更易于与Spring AOP集成.

我们今天要讨论的不是BeanFactory或ApplicationContext的实现原理,而是ApplicationContext的实际应用.

提问

在实际工作中,我们经常遇到接口和多个实现类的情况,并且在不同条件下将使用不同的实现类. 从使用的角度来看,有些用法类似于SPI,

spring常用的接口和类_spring常用工具类_常用类之tcp连接类s

但是,由于使用SPI并不是很方便,我该怎么办?我们可以使用ApplicationContext的getBeansOfType来获得所需的结果.

首先让我们看一下该方法的签名

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

从上面的代码中我们可以看到,此方法可以返回接口的所有实现类(前提是所有实现类都必须由Spring IoC容器管理).

让我们看看我们遇到的问题.

“假设从A点到B点有多种运输方式. 每种运输方式的成本是不同的spring常用的接口和类,可以根据乘客的需求进行选择”(嗯,我承认这很la脚需求,

但是您可以想到类似的要求,例如付款方式和快递公司. 页面上提供了几个选项,并且业务代码根据不同的选项选择要调用的不同的实现类实例.

实施

常用类之tcp连接类s_spring常用工具类_spring常用的接口和类

回到我们的示例,根据这种运输方式的需求,我们的设计如下: 有一个运输方式的接口,该接口有两种模式,一种查询成本,一种查询运输方式. 在运输方式上,我们同时使用枚举类型类来识别交通类型.

我们还需要一个工厂类来根据流量类型标识符找到流量类型的Bean实例,以便使用该实例获取流量类型的详细信息以及该流量类型的操作.

图片描述

代码如下:

接口:

/**
 * 交通方式
 */
public interface TrafficMode {
    /**
     * 查询交通方式编码
     * @return 编码
     */
    TrafficCode getCode();
    /**
     * 查询交通方式的费用,单位:分
     * @return 费用
     */
    Integer getFee();
}

枚举:

/**
 * 交通类型枚举
 */
public enum TrafficCode {
    TRAIN,
    BUS
}

常用类之tcp连接类s_spring常用工具类_spring常用的接口和类

该接口有两个实现类:

/**
 * 汽车方式
 */
@Component
public class BusMode implements TrafficMode {
    @Override
    public TrafficCode getCode() {
        return TrafficCode.BUS;
    }
    @Override
    public Integer getFee() {
        return 10000;
    }
}

/**
 * 火车方式
 */
@Component
public class TrainMode implements TrafficMode {
    @Override
    public TrafficCode getCode() {
        return TrafficCode.TRAIN;
    }
    @Override
    public Integer getFee() {
        return 9000;
    }
}

工厂类:

/**
 * 交通方式工厂类
 */
@Component
public class TrafficModeFactory implements ApplicationContextAware {
    private static Map<TrafficCode, TrafficMode> trafficBeanMap;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, TrafficMode> map = applicationContext.getBeansOfType(TrafficMode.class);
        trafficBeanMap = new HashMap<>();
        map.forEach((key, value) -> trafficBeanMap.put(value.getCode(), value));
    }
    public static <T extends TrafficMode> T getTrafficMode(TrafficCode code) {
        return (T)trafficBeanMap.get(code);
    }
}

验证

有了上面的代码之后,我们来看一下通过单元测试的效果. 单元测试代码段如下:

    @Test
    public void testGetTrafficMode() {
        TrafficMode mode = TrafficModeFactory.getTrafficMode(TrafficCode.BUS);
        Assert.assertEquals(mode.getFee().intValue(), 10000);
        mode = TrafficModeFactory.getTrafficMode(TrafficCode.TRAIN);
        Assert.assertEquals(mode.getFee().intValue(), 9000);
    }

常用类之tcp连接类s_spring常用的接口和类_spring常用工具类

运行后结果如何?它必须通过.

关于SPI

本文在这里,一些学生可能会问: 这与SPI有什么区别? SPI也可以实现相同的功能. 首先,让我解释一下SPI是JDK的内置函数. 尽管历史比较悠久,但这并不意味着它不好,并且某些方案不是SPI(例如JDBC).

我们阐明了SPI是什么以及它的设计用途. SPI的全名是服务提供商接口(Service Provider Interface),因为它是针对制造商或插件的. 更为经典的用法是JDBC. Java提供了一个标准的JDBC接口spring常用的接口和类,每个供应商都提供了自己的驱动程序实现. 以下是JDBC驱动程序接口:

public interface Driver {
    Connection connect(String var1, Properties var2) throws SQLException;
    boolean acceptsURL(String var1) throws SQLException;
    DriverPropertyInfo[] getPropertyInfo(String var1, Properties var2) throws SQLException;
    int getMajorVersion();
    int getMinorVersion();
    boolean jdbcCompliant();
    Logger getParentLogger() throws SQLFeatureNotSupportedException;
}

以下是由MySQL的JDBC驱动程序实现的SPI配置:

图片描述

我们已经了解了SPI. 在这里,我们只想证明前面的示例中使用的SPI和AP具有不同的适用场景.

在前面的示例中,我们使用了什么? Spring的API,API的全称是Application Programming Interface(应用程序编程接口),在应用程序内部,使用API​​是一种非常方便且最直接的方法.

总而言之,就是在编程中,我们使用API​​最多. 当然,我们也将使用SPI(尽管我们并不是严格意义上的制造商或插件),使用SPI也是解决特定情况下问题的一种方式.

有关SPI的更多信息,将来还会有专门的文章.

【附加】关于SPI的协议: 当服务提供者提供服务接口的实现时,还将在jar包的META-INF / services /目录中创建一个以服务接口命名的文件. 该文件是实现服务接口的具体实现类. 当外部程序组装此模块时,您可以通过META-INF / services / jar包中的配置文件找到特定的实现类名称,然后加载并实例化它以完成模块注入. 基于这种约定,可以很好地找到服务接口的实现类,而无需在代码中用公式表示. jdk提供了一个用于服务实现搜索的工具类: java.util.ServiceLoader,通过其load方法,您可以通过传入接口来获取其实现类.


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-213414-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...