java - 改为调用其他方法

标签 java reflection annotations

我有两种方法,其中一种带有注释,比方说:

@ReplacingMethod(bar)
public void foo() { ... }

public void bar { ... }

是否可以在调用 foo 时调用 bar 而不是 foo,而不跳转到 foo 的主体?我对此做了一些研究,但无法通过反射设置返回值。有什么建议吗?

最佳答案

您可以使用 Aspect Oriented Programming 来实现此目的,例如与 Spring AOP 。我不认为你可以在没有 AOP 的情况下改变纯 Java 中的方法实现。

让我举一个例子,说明如何使用 Spring AOP 实现您的要求。首先,定义您的注释:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ReplacingMethod {
    String value();
}

然后定义一个方面来执行方法的实际替换:

@Aspect // aspect is a module encapsulating your replacing functionality
public class ReplacingAspect {
    // pointcut gives an expression selecting the "joint points" to be intercepted
    @Pointcut("@annotation(example.annotation.ReplacingMethod)")
    public void methodToBeReplaced() { }

    // advice defining the code executed at joint points selected by given pointcut;
    // in our case @Around is executed instead of the method call selected by pointcut methodToBeReplaced()
    @Around("methodToBeReplaced()")
    public void replaceMethodCall(ProceedingJoinPoint pjp) throws Throwable {
        // get reference to the method to be replaced
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        // extract the name of the method to be called from ReplacingMethod annotation
        ReplacingMethod replacingMethodAnnotation = method.getAnnotation(ReplacingMethod.class);
        String methodToCallName = replacingMethodAnnotation.value();
        // use reflection to call the method
        Method methodToCall = pjp.getTarget().getClass().getMethod(methodToCallName);
        methodToCall.invoke(pjp.getTarget());
    }
}

现在,假设您有一个 TestClass 类,您已在其中应用了 @ReplacingMethod 注释,

public class TestClass {
    @ReplacingMethod("bar")
    public void foo() { System.out.println("foo"); }
    public void bar() { System.out.println("bar"); }
}

最后一个缺失的部分是创建启用 AOP 并应用 ReplacingAspectTestClass 实例:

public class Main {
    public static void main(String... args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);  // create Spring context that enables AOP under the hood
        TestClass testObject = context.getBean(TestClass.class); // we get reference to TestClass instance from context; calling on a plain new instance wouldn't work
        testObject.foo(); // prints "bar" !
    }

    @EnableAspectJAutoProxy // enables AOP support
    @Configuration
    public static class TestConfiguration {
        @Bean public TestClass testClass() { return new TestClass(); }
        @Bean public ReplacingAspect aspect() { return new ReplacingAspect(); } // enables our ReplacingAspect
    }
}

您可以在 GitHub 查看整个工作示例.

关于java - 改为调用其他方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32417371/

相关文章:

java - 在 Java 运行时修改内联常量

Java Reflection - 获取数组对象的大小

java - @SafeVarargs 注释的存在/不存在真的是一个有用的区别吗?

android - 将 @SuppressLint ("RestrictedApi") 与 AndroidX 库一起使用是否安全?

java : annotations before method parameters

java - 检查使用 JAVA(一个 jsp)选中了哪些复选框

java - PyLucene : lucene. initVM() 在 linux RHEL7 上导致段错误

java - 使用 Maven 通过 swing 客户端构建 Java EE 6 项目

java - 为什么我的属性值没有打印?

pointers - 如何使用reflect获取指针的底层类型?