Spring 自定义集合实现策略
日常开发中,如果遇到复杂业务通常会用一个接口实现多个实现类。需要根据对应参数判断获取不同实现类。例如支付场景,根据选择支付方式,选择相应路由。如果实现类不多,通常会这样。如果实现类多了,每次新增一个实现,还需要修改路由,写的就恶心了。有没有什么好的方式可以解决呢?
if(rule1){return a 的实例;
}if(rule12){retuen 实现类b的实例;
}
方法一
利用Spring applicationContext
Map<String, xx> beans = applicationContext.getBeansOfType(xx.class);然后封装工具类,根据key从map 获取对应实现类伪代码如下private static Map<String,xxService> serviceMap = new HashMap<>();Map<String, xxService> beans = applicationContext.getBeansOfType(xxService.class);for (xxService s : beans.values()) {if(serviceMap.putIfAbsent(s.type(), s) != null){throw new RuntimeException(s.class.getSimpleName() + " 已经存在[" + s.type() + "]类型");}}或者直接注入
@Autowired
List<xxService> xxList;
通常也是使用这种方式比较多,但是感觉还是不够通用。新增了一种多态实现,还是需要改代码,存入map
方法二Spring Bean选择器模式
利用spring的注入功能,使用注解来实现依赖注入,这里自定义了列表,。其中用到了CustomCollectionEditor类。直接上代码
/*** @author: one* @date: 2024/7/27 17:29**/
public interface MatchBean<K> {boolean match(K factor);
}
/*** @author: one* @date: 2024/7/27 17:29**/
public interface MultiServiceFactory<E extends MatchBean<K>, K> extends List<E> {E getBean(K factor);List<E> getBeanList(K factor);
}
/*** @author: one* @date: 2024/7/27 17:29**/
public class MultiServiceFactoryImpl<E extends MatchBean<K>, K> extends ArrayList<E> implements MultiServiceFactory<E, K>, Serializable {@Overridepublic E getBean(K factor) {Iterator<E> itr = iterator();while (itr.hasNext()) {E beanMatch = itr.next();if (beanMatch.match(factor)) {return beanMatch;}}return null;}@Overridepublic List<E> getBeanList(K factor) {Iterator<E> itr = iterator();while (itr.hasNext()) {E beanMatch = itr.next();if (!beanMatch.match(factor)) {itr.remove();}}return this;}
}
MultiServiceFactoryEditor类的命名,必须是接口类MultiServiceFactory的类名+Editor组成。
super(MultiServiceFactoryImpl.class),通过CustomCollectionEditor注册了转换器。
spring-beans这个jar的BeanUtils类的findEditorByConvention方法里面,可以看到editor类名的拼接过程。targetTypeName 为工厂类的类名,editorName 为工厂类所对应的editor类名public class MultiServiceFactoryEditor extends CustomCollectionEditor {public MultiServiceFactoryEditor() {super(MultiServiceFactoryImpl.class);}
}
然后在你的多态实现MatchBean接口即可,上demo
public interface Animals extends MatchBean<String> {String name();String run();@Overridedefault boolean match(String factor) {return this.name().equals(factor);}
}
@Service
public class Dog implements Animals {@Overridepublic String name() {return "dog";}@Overridepublic String run() {return "狗跑";}
}
@Service
public class Cat implements Animals {@Overridepublic String name() {return "cat";}@Overridepublic String run() {return "猫跑";}
}
测试
@Autowiredprivate MultiServiceFactory<Animals, String> multiServiceFactory;@PostConstructpublic void init() {System.out.println(multiServiceFactory.getBean("dog").run());System.out.println(multiServiceFactory.getBean("cat").run());}