在学习spring选择器的时候,找到了这篇文章:
https://zhuanlan.zhihu.com/p/100035474
里面用到了spring的注入功能,使用注解来实现依赖注入,这里自定义了列表,然后把两个service注入进去。其中用到了CustomCollectionEditor类,这个类继承了jdk的PropertyEditorSupport类。PropertyEditorSupport类是用来实现属性值的转换功能。比如说处理xml文件里面字符串到java对象的转换。同类型的service注册到map里面去,这里实现的是map到list的转换。如果不加转换,会报org.springframework.beans.factory.UnsatisfiedDependencyException异常。详情见参考。
现在说说当前这个转换。参考代码如下:
public interface MatchingBean<K> {
boolean matching(K factor);
}
通过matching方法来匹配具体的bean对象,bean要实现这个接口。
public interface MyFactoryList<E extends MatchingBean<K>, K> extends List<E> {
E getBean(K factor);
List<E> getBeanList(K factor);
}
通过getBean方法来获取bean对象。
MyFactoryList的实现类:
public class MyFactoryArrayList<E extends MatchingBean<K>, K> extends ArrayList<E> implements MyFactoryList<E, K>, Serializable {
@Override
public E getBean(K factor) {
for (E beanMatch : this) {
if (beanMatch.matching(factor)) {
return beanMatch;
}
}
return null;
}
@Override
public List<E> getBeanList(K factor) {
removeIf(beanMatch -> !beanMatch.matching(factor));
return this;
}
}
public class MyFactoryListEditor extends CustomCollectionEditor {
public MyFactoryListEditor() {
super(MyFactoryArrayList.class);
}
}
MyFactoryListEditor类的命名,必须是接口类MyFactoryList的类名+Editor组成。
super(MyFactoryArrayList.class),通过CustomCollectionEditor注册了转换器。
spring-beans这个jar的BeanUtils类的findEditorByConvention方法里面,可以看到editor类名的拼接过程。targetTypeName 为工厂类的类名,editorName 为工厂类所对应的editor类名。代码如下:
String targetTypeName = targetType.getName();
String editorName = targetTypeName + "Editor";
public interface BuyService extends MatchingBean<String> {
String goShopping();
}
goShopping是业务接口。
下面是两个业务的实现代码:
@Service
public class JingdongService implements BuyService {
@Override
public String goShopping() {
return "Shopping in JD";
}
@Override
public boolean matching(String factor) {
return "jd".equals(factor);
}
}
@Service
public class TaobaoService implements BuyService {
@Override
public String goShopping() {
return "Shopping in Taobao";
}
@Override
public boolean matching(String factor) {
return "taobao".equals(factor);
}
}
测试代码:
@SpringBootTest
class SelectorApplicationTests {
@Autowired
MyFactoryList<BuyService,String> factoryList;
@Autowired
List<BuyService> buyServices;
@Test
void contextLoads() {
BuyService shop = factoryList.getBean("jd");
System.out.println(shop.goShopping());
System.out.println(buyServices.size());
}
}
factoryList通过@Autowired实现依赖注入,buyServices本身是list容器,spring已经内置了这个转换。
参考:
https://blog.csdn.net/zhonglin_li/article/details/51571093
https://zhuanlan.zhihu.com/p/100035474