前文中提到通过策略模式代替switch-case的方式,在实际使用中将接口通过bean获得,然后去调用即可;
实际操作中发现,springboot在通过@Autowired
或者@Resource
方式注入时会出现部分问题;
针对以上替代switch-case形式的策略模式会产生很多接口的实现类,注入时需要确定bean的具体类型使用@Qualifier+@Autowired
或者 @Resource (name="beanName")
的方式时均只能获得一个bean 不能满足使用接口去调用的方式;
以下是百度到的其他解决方式,未能成功,不排除我本身代码问题
// 1、使用 List<ServiceInterface> beanNames的方式
// 或者使用@Resource 注入
// 或者使用 Map<String,Class>的方式 前者为beanName 后者为具体实现类;
@Autowired
private List<ServiceInterface> serviceInterfaces;
public static void main(String[] args) {
int param= 1;
for (HandleMapClientOperateService serviceInterface : serviceInterfaces) {
if(serviceInterface.isDo(param)){
serviceInterface.doIt();
}
}
}
另一种基于反射形式获取beans,也是参考另一个大佬的实现;
public static void main(String[] args) throws Exception {
List<ServerInterface> serviceInterfaces= new ArrayList<>();
List<Class> clazzs = getAllInterfaceAchieveClass(HandleMapClientOperateService.class);
for (Class clazz : clazzs) {
serviceInterfaces.add((ServerInterface) clazz.newInstance());
}
//打印Class对象
for (ServerInterfacecla : serviceInterfaces) {
if (cla.isDo(1)) {
cla.doIt(1);
}
}
}
@SneakyThrows
public static List<HandleMapClientOperateService> getServiceImpl() {
List<HandleMapClientOperateService> services = new ArrayList<>();
List<Class> clazzs = getAllInterfaceAchieveClass(HandleMapClientOperateService.class);
for (Class clazz : clazzs) {
services.add((HandleMapClientOperateService) clazz.newInstance());
}
return services;
}
public static List<Class> getAllInterfaceAchieveClass(Class clazz) {
ArrayList<Class> list = new ArrayList<>();
//判断是否是接口
if (clazz.isInterface()) {
try {
ArrayList<Class> allClass = getAllClassByPath(clazz.getPackage().getName());
/**
* 循环判断路径下的所有类是否实现了指定的接口
* 并且排除接口类自己
*/
for (int i = 0; i < allClass.size(); i++) {
//排除抽象类
if (Modifier.isAbstract(allClass.get(i).getModifiers())) {
continue;
}
//判断是不是同一个接口
if (clazz.isAssignableFrom(allClass.get(i))) {
if (!clazz.equals(allClass.get(i))) {
list.add(allClass.get(i));
}
}
}
} catch (Exception e) {
System.out.println("出现异常");
}
}
return list;
}
/**
* 从指定路径下获取所有类
*
* @return
*/
public static ArrayList<Class> getAllClassByPath(String packagename) {
ArrayList<Class> list = new ArrayList<>();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String path = packagename.replace('.', '/');
try {
ArrayList<File> fileList = new ArrayList<>();
Enumeration<URL> enumeration = classLoader.getResources(path);
while (enumeration.hasMoreElements()) {
URL url = enumeration.nextElement();
fileList.add(new File(url.getFile()));
}
for (int i = 0; i < fileList.size(); i++) {
list.addAll(findClass(fileList.get(i), packagename));
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
private static ArrayList<Class> findClass(File file, String packagename) {
ArrayList<Class> list = new ArrayList<>();
if (!file.exists()) {
return list;
}
File[] files = file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
assert !file2.getName().contains(".");//添加断言用于判断
ArrayList<Class> arrayList = findClass(file2, packagename + "." + file2.getName());
list.addAll(arrayList);
} else if (file2.getName().endsWith(".class")) {
try {
//保存的类文件不需要后缀.class
list.add(Class.forName(packagename + '.' + file2.getName().substring(0,
file2.getName().length() - 6)));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
return list;
}
另外在以上方式中,发现其他的service 无法注入到方法中,通过 implements ApplicationContextAware
的方式,获取bean;