為什么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 ,對已存在的類進行解析,可以讓我們在沒有源碼的情況下,對類進行操作。