Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 改为调用其他方法_Java_Reflection_Annotations - Fatal编程技术网

Java 改为调用其他方法

Java 改为调用其他方法,java,reflection,annotations,Java,Reflection,Annotations,我有两种方法,其中一种带有注释,比如: @ReplacingMethod(bar) public void foo() { ... } public void bar { ... } 当调用foo时,是否可以调用bar而不是foo,而不必跳入foo的主体?我对此做了一些研究,但无法通过反射设置返回值。有什么建议吗?您可以使用,例如使用。我认为在没有AOP的情况下,您无法在纯Java中更改方法实现 让我举一个例子,说明如何使用SpringAOP实现您的要求。首先,定义注释: @Target(E

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

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

public void bar { ... }

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

您可以使用,例如使用。我认为在没有AOP的情况下,您无法在纯Java中更改方法实现

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

@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());
    }
}
现在,假设您已经在class
TestClass
中应用了
@ReplacingMethod
注释

public class TestClass {
    @ReplacingMethod("bar")
    public void foo() { System.out.println("foo"); }
    public void bar() { System.out.println("bar"); }
}
最后一个缺少的部分是在启用AOP并应用
replacingspect
的情况下创建
TestClass
的实例:

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
    }
}

您可以在上查看整个工作示例。

反射不能更改类的模式,也不能更改其行为。它只能调用(可能是隐藏的)功能

如果要用另一个方法调用替换一个方法调用,请尝试使用字节码库作为或。这些工具允许您更改类定义和行为(即使在运行时有一些限制)


使用AOP的方法更简单,但它没有那么灵活,而且它的类路径占用空间更大。

@ReplacingMethod看起来像什么?当我在谷歌上搜索这个问题时,我只发现了这个问题。Java中没有标准的功能来实现这一点,但您可以使用诸如或之类的框架来实现这一点。