class TargetClassVisitor extends ClassVisitor {
    static final Logger log = LoggerFactory.getLogger(TargetClassVisitor.class);

    private boolean isFinal;
    private List<MethodBean> methods = new ArrayList<>();
    private List<MethodBean> declaredMethods = new ArrayList<>();
    private List<MethodBean> constructors = new ArrayList<>();

    private final ClassLoader classLoader;

    public TargetClassVisitor(ClassLoader classLoader) {
        super(AsmProxy.ASM_VERSION);
        this.classLoader = classLoader;
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);

        if ((access & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL) {
            isFinal = true;
        }

        if (superName != null) {
            List<MethodBean> beans = initMethodBeanByParent(superName);

            if (beans != null && !beans.isEmpty()) {
                for (MethodBean bean : beans) {
                    if (!methods.contains(bean)) {
                        methods.add(bean);
                    }
                }
            }
        }
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {<FILL_FUNCTION_BODY>}

    public boolean isFinal() {
        return isFinal;
    }

    public List<MethodBean> getMethods() {
        return methods;
    }

    public List<MethodBean> getDeclaredMethods() {
        return declaredMethods;
    }

    public List<MethodBean> getConstructors() {
        return constructors;
    }

    private List<MethodBean> initMethodBeanByParent(String superName) {
        try {
            if (superName != null && !superName.isEmpty()) {
                if(superName.equals("java/lang/Object")){
                    return null;
                }

                URL superNameUrl = classLoader.getResource(superName.replace('.', '/') + ".class");
                if (superNameUrl == null) {
                    throw new IOException("Class not found: " + superName);
                }

                ClassReader reader;
                try (InputStream in = superNameUrl.openStream()) {
                    reader = new ClassReader(in);
                }

                TargetClassVisitor visitor = new TargetClassVisitor(classLoader);
                reader.accept(visitor, ClassReader.SKIP_DEBUG);
                List<MethodBean> beans = new ArrayList<>();
                for (MethodBean methodBean : visitor.methods) {
                    // 跳过 final 和 static
                    if ((methodBean.access & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL
                            || (methodBean.access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC) {
                        continue;
                    }
                    // 只要 public
                    if ((methodBean.access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC) {
                        beans.add(methodBean);
                    }
                }
                return beans;
            }
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
        }

        return null;
    }
}

        if ("<init>".equals(name)) {
            // 构造方法
            MethodBean constructor = new MethodBean(access, name, descriptor);
            constructors.add(constructor);
        } else if (!"<clinit>".equals(name)) {
            // 其他方法
            if ((access & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL
                    || (access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC) {
                return super.visitMethod(access, name, descriptor, signature, exceptions);
            }

            MethodBean methodBean = new MethodBean(access, name, descriptor);

            //public 给 declaredMethods + methods
            if ((access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC
                    && (access & Opcodes.ACC_ABSTRACT) != Opcodes.ACC_ABSTRACT) {

                if (declaredMethods.contains(methodBean) == false) {
                    declaredMethods.add(methodBean);
                }

                if (methods.contains(methodBean) == false) {
                    methods.add(methodBean);
                }
            }

            //protected 给 declaredMethods
//            if ((access & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED
//                    && (access & Opcodes.ACC_ABSTRACT) != Opcodes.ACC_ABSTRACT) {
//
//                if (declaredMethods.contains(methodBean) == false) {
//                    declaredMethods.add(methodBean);
//                }
//            }
        }

        return super.visitMethod(access, name, descriptor, signature, exceptions);
    
<methods>public org.objectweb.asm.ClassVisitor getDelegate() ,public void visit(int, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) ,public org.objectweb.asm.AnnotationVisitor visitAnnotation(java.lang.String, boolean) ,public void visitAttribute(org.objectweb.asm.Attribute) ,public void visitEnd() ,public org.objectweb.asm.FieldVisitor visitField(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object) ,public void visitInnerClass(java.lang.String, java.lang.String, java.lang.String, int) ,public org.objectweb.asm.MethodVisitor visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) ,public org.objectweb.asm.ModuleVisitor visitModule(java.lang.String, int, java.lang.String) ,public void visitNestHost(java.lang.String) ,public void visitNestMember(java.lang.String) ,public void visitOuterClass(java.lang.String, java.lang.String, java.lang.String) ,public void visitPermittedSubclass(java.lang.String) ,public org.objectweb.asm.RecordComponentVisitor visitRecordComponent(java.lang.String, java.lang.String, java.lang.String) ,public void visitSource(java.lang.String, java.lang.String) ,public org.objectweb.asm.AnnotationVisitor visitTypeAnnotation(int, org.objectweb.asm.TypePath, java.lang.String, boolean) <variables>protected final int api,protected org.objectweb.asm.ClassVisitor cv