mardi 20 août 2019

How to define new annotations for public methods in class via Byte Buddy

I'm trying to annotate all public methods in my class annotated with my custom annotation using Byte Buddy.

I've already tried to use the code from the comment here: Add method annotation at runtime with Byte Buddy

Java version: 1.8. The app is for testing microservices. Application is running via Spring Boot. I try to annotate all needed methods in my app with annotation with value depending on method name.

            <dependency>
                <groupId>org.reflections</groupId>
                <artifactId>reflections</artifactId>
                <version>0.9.11</version>
            </dependency>
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy</artifactId>
                <version>1.10.1</version>
            </dependency>
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy-agent</artifactId>
                <version>1.10.1</version>
            </dependency>  


Working method:


import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import io.qameta.allure.Step;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.MemberAttributeExtension;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.matcher.ElementMatchers;
import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

public class StackOverflowExample {

    private static final String REGEX = "some-package";

    public void configureAnnotation() {
        Reflections reflections = getReflections();
        Set<Class<?>> allClasses = reflections.getSubTypesOf(Object.class);
        allClasses.forEach(clazz -> {
            if (clazz.isAnnotationPresent(ConfigureSteps.class)) {
                List<Method> publicMethods = Arrays.stream(clazz.getDeclaredMethods())
                                                   .filter(method -> Modifier.isPublic(method.getModifiers()))
                                                   .collect(Collectors.toList());
                AnnotationDescription annotationDescription = AnnotationDescription.Builder.ofType(Step.class)
                                                                                           .define("value", "new annotation")
                                                                                           .build();
                publicMethods.forEach(method -> new ByteBuddy().redefine(clazz)
                                                               .visit(new MemberAttributeExtension.ForMethod()
                                                                              .annotateMethod(annotationDescription)
                                                                              .on(ElementMatchers.anyOf(method)))
                                                               .make());
            }
        });
    }

    private Reflections getReflections() {
        return new Reflections(new ConfigurationBuilder().setScanners(new SubTypesScanner(false), new ResourcesScanner())
                                                         .addUrls(ClasspathHelper.forJavaClassPath())
                                                         .filterInputsBy(new FilterBuilder().include(REGEX)));
    }
}

I call configureAnnotation method before all the tests using JUnit @BeforeAll annotation. Method is invoked without issues but methods in my class with ConfigureSteps annotation aren't annotated with Step annotation. What is the problem? Or may be I should build Agent like it is in tutorial here: http://bytebuddy.net/#/tutorial And in this case what way should I override transform method?





Aucun commentaire:

Enregistrer un commentaire