繁体   English   中英

Java Annotations可以帮助我解决这个问题吗?

[英]Can Java Annotations help me with this?

我想知道是否有一种方法可以指定在类方法之前调用方法。 我知道这样的事情应该是可能的,因为JUnit在before()之前,我想要做的是类似的。

这是我想做的具体例子

class A {

 public void init(int a) {
  System.out.println(a);
 }

 @magic(arg=1)
 public void foo() { 
   //
 }

 public static void main() {
   A a = new A();
   a.foo();
 }
}

//Output: 1

基本上我想要一个注释告诉编译器或jvm调用init()之前foo()

如果您有interface A您可以使用ProxyInvocationHandler内部invoke方法包装此接口的实例,您可以自由检查方法是否已注释并执行某些操作,具体取决于:

class Initalizer implements InvocationHandler {
    private A delegate;
    Initializer(A delegate) {
        this.delegate = delegate;
    }

    public Object invoke(Object proxy, Method method, Object[] args) {
        if (method.isAnnotationPresent(magic.class)) {
            magic annotation = method.getAnnotation(magic.class);
            delegate.init(magic.arg);
        }
        method.invoke(delegate, args);
    }
} 
A realA = ...;
A obj = Proxy.newProxyInstance(A.class.getClassLoader(), new Class[] {A.class}, new Initializer(realA));

或者您可以尝试使用AspectJ的“之前”建议。 它会像下一个:

@Aspect
public class Initializer {
    @Before("@annotation(your.package.magic) && target(obj) && @annotation(annotation)")
    private void initialize(A obj, magic annotation) {             
         a.init(annotation.arg);
    }
}

我不确定片段是否有效,它们只是说明了想法。

你为什么做这个? 您是否试图避免使用具有许多参数的构造函数(使用setter然后调用init)或者您是否避免使用许多具有相似参数的构造函数? 如果是这种情况,您可以使用构建器模式。

public class Foo {
int a, b, c, d, e;
Foo(int a, int b, int c, int d, int e) { this.a=a; /*etc*/ }
}

public class FooBuilder {
int a,b,c,d,e;
FooBuilder A(int a) { this.a=a; return this;}
FooBuilder B(int b) { this.b=b; return this;}
//etc
Foo create(){ return new Foo(a,b,c,d,e);
}

如果这不起作用,我建议调查AOP。 我将使用注释[也许是@requires('init')等标记必须具有init()的方法)并使AOP框架插入正确的代码。 请注意,多个init没有副作用,或者您在has_init_been_called状态下执行了正确的同步。

只需在foo()的开头调用Init()?

AOP通过所谓的切入点来实现这一点,AspectJ可能拥有您所需要的功能。

简单来说,你可以在你的foo()方法之前添加一个调用init()的方法

在java语言中没有直接的方法。 您在JUnit中看到的是通过首先调用@Before注释的方法来决定如何运行方法的框架。 找到带注释的方法并运行它们非常容易,但这是调用者的责任。

您提出的问题太简单,无法找到正确的解决方案。 AspectJ确实通过操作字节代码来解决这个问题(当通过改变字节码来调用foo()时实际调用init()方法来实现),但我无法想象将其作为一个问题的黑客。

如果您可以向此类提供接口或包装器对象,则可以这样做。 但我建议你在一个单独的问题中首先发布让你陷入这种情况的丑陋黑客,然后发布你当前的黑客解决方案如何要求拦截方法调用以及为什么会这样,如果有更好的解决方法。 这样我们就可以更好地帮助解决潜在需求。

看看AspectJ 它会帮助你做你想要的。

我假设这里的问题如下:

  1. 您有一个可以部分构建对象的构造函数,但由于必须构造类的方式,因此无法完全构建它。 (我想不出一个随便的例子。)
  2. 所以你需要一个完成构造的init()方法。
  3. 所以你想要保证在构造函数之后立即调用init()

我的建议是使用工厂对象或方法。 最简单的方法是使构造函数为private,使用construct()的参数或类似的东西添加一个construct()方法,然后让construct()方法创建对象并调用init() ,然后返回它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM