1. 程式人生 > 其它 >使用javassist動態為方法添加註解

使用javassist動態為方法添加註解

    Reflections reflections = new Reflections(new ConfigurationBuilder()
            //指定路徑URL
            .forPackages(packageName)
            //新增子類掃描工具
            .addScanners(new SubTypesScanner())
            //新增 屬性註解掃描工具
            .addScanners(new FieldAnnotationsScanner())
            //新增 方法註解掃描工具
            .addScanners(new MethodAnnotationsScanner())
            //新增方法引數掃描工具
            .addScanners(new MethodParameterScanner())
    );

    Set<Method> methodKafkaSet3 = reflections.getMethodsAnnotatedWith(KafkaListener.class);
    Set<Method> methodSet = reflections.getMethodsAnnotatedWith(MyListener.class);
    if (!CollectionUtils.isEmpty(methodSet)) {
        for (Method method : methodSet) {

            String className = method.getDeclaringClass().getName();
            String methodName = method.getName();

            //指定類
            ClassPool aDefault = new ClassPool();
            ClassClassPath classPath = new ClassClassPath(this.getClass());
            aDefault.insertClassPath(classPath);
            CtClass ctClass = aDefault.get(className);

            //指定方法
            CtMethod ctMethod = ctClass.getDeclaredMethod(methodName);
            MethodInfo methodInfo = ctMethod.getMethodInfo();
            ConstPool constPool = methodInfo.getConstPool();

            //要新增的註解
            AnnotationsAttribute methodAttr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
            Annotation methodAnnot = new Annotation("org.springframework.kafka.annotation.KafkaListener", constPool);

            // 新增方法註解
            StringMemberValue[] elements = {new StringMemberValue(String.join("-", "elk-event", env), constPool)};
            ArrayMemberValue amv = new ArrayMemberValue(constPool);
            amv.setValue(elements);
            methodAnnot.addMemberValue("topics", amv);
            methodAnnot.addMemberValue("groupId", new StringMemberValue("bury-point-fat", constPool));
            methodAttr.addAnnotation(methodAnnot);
            ctMethod.getMethodInfo().addAttribute(methodAttr);

            // 新增引數註解
            ParameterAnnotationsAttribute parameterAtrribute = new ParameterAnnotationsAttribute(
                    constPool, ParameterAnnotationsAttribute.visibleTag);
            Annotation paramAnnot = new Annotation("org.springframework.messaging.handler.annotation.Payload", constPool);
            paramAnnot.addMemberValue("value", new StringMemberValue("",constPool));
            Annotation[][] paramArrays = new Annotation[1][1];
            paramArrays[0][0] = paramAnnot;
            parameterAtrribute.setAnnotations(paramArrays);
            ctMethod.getMethodInfo().addAttribute(parameterAtrribute);

            //寫入class檔案
            String path = method.getDeclaringClass().getResource("").getPath();
            ctClass.writeFile(path);
            ctClass.defrost();

        }
    }

備註: 獲取類路徑和寫入class檔案的另一種方式:
 String path=method.getDeclaringClass().getResource(method.getDeclaringClass().getSimpleName()+".class").getPath();
 
//把生成的class檔案寫入檔案
 byte[] byteArr = new byte[0];
 byteArr = ctClass .toBytecode();
 FileOutputStream fos = null;
 fos = new FileOutputStream(new File(path));
 fos.write(byteArr);
 fos.close();