为什么80%的码农都做不了架构师?>>>
ASM 判定一个类,实现了指定接口
技术支持
ASM 中,ClassReader 类:对已存在的进行解析,并提供获取类信息的方法。
通过 ClassReader ,实现对一个类的解析。
处理流程
依据如下流程,判断出一个类是否实现了某个接口:
- 循环判断是否实现目标接口
- 递归判断父接口是否存在目标接口
- 递归判断父类是否实现目标接口
具体实现
具体实现代码如下 :
package utils;import org.objectweb.asm.ClassReader;import java.io.IOException;
import java.util.Set;/*** 判断某类是否实现了指定接口集合** @author pengpj* @date 2018/11/27*/
public class SpecifiedInterfaceImplementionChecked {/*** 判断是否实现了指定接口** @param reader class reader* @param interfaceSet interface collection* @return check result*/public static boolean hasImplSpecifiedInterfaces(ClassReader reader, Set<String> interfaceSet) {if (isObject(reader.getClassName())) {return false;}try {if (containedTargetInterface(reader.getInterfaces(), interfaceSet)) {return true;} else {ClassReader parent = new ClassReader(reader.getSuperName());return hasImplSpecifiedInterfaces(parent, interfaceSet);}} catch (IOException e) {return false;}}/*** 检查当前类是 Object 类型** @param className class name* @return checked result*/private static boolean isObject(String className) {return "java/lang/Object".equals(className);}/*** 检查接口及其父接口是否实现了目标接口** @param interfaceList 待检查接口* @param interfaceSet 目标接口* @return checked result* @throws IOException exp*/private static boolean containedTargetInterface(String[] interfaceList, Set<String> interfaceSet) throws IOException {for (String inter : interfaceList) {if (interfaceSet.contains(inter)) {return true;} else {ClassReader reader = new ClassReader(inter);if (containedTargetInterface(reader.getInterfaces(), interfaceSet)) {return true;}}}return false;}}
测试用例
部分测试用例如下:
private static Set<String> set;static {if (set == null) {set = new HashSet<>();}set.add("com/cvte/myou/apm/agent/utils/SpecifiedInterfaceImplCheckedTest$A");}@Testpublic void hasImplSpecifiedInterfacesTest() throws IOException {Assert.assertEquals(true, SpecifiedInterfaceImplChecked.hasImplSpecifiedInterfaces(new ClassReader(B.class.getName()), set));Assert.assertEquals(true, SpecifiedInterfaceImplChecked.hasImplSpecifiedInterfaces(new ClassReader(C.class.getName()), set));}@Testpublic void hasImplSpecifiedInterfacesObjectTest() throws IOException {Assert.assertEquals(false, SpecifiedInterfaceImplChecked.hasImplSpecifiedInterfaces(new ClassReader(Object.class.getName()), set));}@Testpublic void hasImplSpecifiedInterfacesInterfaceTest() throws IOException {Assert.assertEquals(true, SpecifiedInterfaceImplChecked.hasImplSpecifiedInterfaces(new ClassReader(D.class.getName()), set));}interface A {void hello();}class B implements A {@Overridepublic void hello() {}}abstract class C implements A {}interface D extends A {}
总结
ASM 中提供了 ClassReader ,对已存在的类进行解析,可以让我们在没有源码的情况下,对类进行操作。