簡體   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