状态机实现】前置——使用Spring的ApplicationContext的getBeansOfType方法实现接口多实现类的动态调用
·
背景
org.springframework.beans及org.springframework.context这两个包是Spring IoC容器的基础,
其中重要的类有BeanFactory,BeanFactory是IoC容器的核心接口,其职责包括:实例化、定位、配置应用程序中的
对象及建立这些对象间的依赖关系。
ApplicationContext作为BeanFactory的子类,在Bean管理的功能上得到了很大的增强,也更易于与Spring AOP集成使用。
今天我们要讨论的并不是BeanFactory或者ApplicationContext的实现原理,而是对ApplicationContext的一种实际应用方式。
应用
在实际工作中,我们经常会遇到一个接口及多个实现类的情况,并且在不同的条件下会使用不同的实现类。
需求
"假设从A点到B点有多种交通方式,每种交通方式的费用不同,可以根据乘客的需要进行选择"
实现
我们的设计如下:有一个交通方式的接口,接口有两个方式,一个查询费用、一个查询该交通方式的类型,同时,我们可以用一个枚举类型类标识交通类型。
我们还需要一个工厂类来根据交通类型标识查找该交通类型的Bean实例,从而使用该实例,获得交通类型的详细信息及该交通类型的操作。

代码如下:
接口:
/**
* 交通方式
*/
public interface TrafficMode {
/**
* 查询交通方式编码
* @return 编码
*/
TrafficCode getCode();
/**
* 查询交通方式的费用,单位:分
* @return 费用
*/
Integer getFee();
}
枚举:
/**
* 交通类型枚举
*/
public enum TrafficCode {
TRAIN,
BUS
}
接口有两个实现类:
/**
* 汽车方式
*/
@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);
}
运行之后的结果呢?必然是通过。
更多推荐


所有评论(0)