2012-02-24 11 views
1

Javaでカスタム注釈を書き込む方法を学習しようとしています。別のオブジェクトを挿入するJavaのカスタム注釈

学習目的のために、注釈を使用してクラスのフィールドを利用できるようにする注釈を作成することにしました。つまり、注入は必要ですが単なるシンプルではありませんがそれも歓迎です。

=============== クラス1 ========= ========================

import java.lang.annotation.ElementType; 
import java.lang.annotation.Inherited; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 


@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
@Inherited 
public @interface AutoInject { 

} 

=================== ============== クラス2 ====================== =

// The class to be injected in Main.java 
public class TestClass0 { 

    void printSomething(){ 
     System.out.println("PrintSomething: TestClass0"); 
    } 

} 

================================= クラス3 ===== =================

import java.lang.annotation.Annotation; 
import java.lang.reflect.Field; 

public class Main { 

    TestClass0 ts0; 
    // Injecting here!! 
    @AutoInject 
    public TestClass0 getTso() { 
     return ts0; 
    } 
    public void setTso(TestClass0 ts) { 
     ts0 = ts; 
    } 

    public static void main(String[] args) { 
     performAnnotationScanOnClass (Main.class); 

     // Create instance 
     Main main = new Main();  
     main.getTso().printSomething(); 

    } 

    public static void performAnnotationScanOnClass(Class<?> clazz) { 
     Field[] fields = clazz.getDeclaredFields(); 

     for (Field field : fields) { 

      Annotation[] annotations = field.getAnnotations(); 
      for (Annotation annotation : annotations) { 

       if (annotation instanceof AutoInject) { 
        AutoInject autoInject = (AutoInject) annotation; 

//      if (field.get(...) == null) 
//       field.set(... , value) 
       } 

      } 

     } 
    } 

} 

static void main()でわかるように、私はTestClass0でメソッドを呼び出そうとしています。私は上記のことがほぼ完了してから長いことを知っていますが、私はちょうど注釈を学習し始め、あなたの指導をしたいと思います。

はどのように我々は新しいまたはgetメソッドが呼び出されたのプロパティのいずれかをinitializezコードの一部を、発火することができます。注釈の使用。私はを変更せずに考えていますメソッドを呼び出します。

ありがとうございます!

+0

あなたのテストの注釈をと思いますが、あなたは本当にCDIを再発明しています。車を改革しないで... – Perception

+6

私は何も再発明していません。私は他者が何をどのように達成し、創造し、作り出したのかを知ろうとしています。あなたはその違いを理解していますか?教育目的のためです。 – momomo

+0

よかったら、それでは幸運にも!私はあなたが多くを学ぶと確信しています。 – Perception

答えて

3

スキャンコード内のフィールドを反復処理していますが、定義した注釈ではメソッドのアノテーションのみが許可されます。つまり、アノテーションは一切表示されません。

Java Beanのプロパティのようにフィールドを使用しようとしているようです。そのままここにあなたのAutoInjectとTestClass0クラスを使用してセッター・インジェクションの例です:

Main.java:

import java.beans.BeanInfo; 
import java.beans.Introspector; 
import java.beans.PropertyDescriptor; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.Method; 

public class Main { 
    public TestClass0 ts0; 

    public TestClass0 getTso() { 
     return ts0; 
    } 

    @AutoInject 
    public void setTso(TestClass0 ts) { 
     ts0 = ts; 
    } 

    public static void main(String[] args) { 
     // Create instance 
     Main main = new Main(); 
     injectDependencies(main).getTso().printSomething(); 

    } 

    public static <T> T injectDependencies(final T obj) { 
     try { 
      Class clazz = obj.getClass(); 
      BeanInfo beanInfo = Introspector.getBeanInfo(clazz); 

      for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { 
       Method readMethod = pd.getReadMethod(); 
       Method writeMethod = pd.getWriteMethod(); 

       if (writeMethod == null) { 
        continue; 
       } 

       Object existingVal = pd.getReadMethod().invoke(obj); 
       if (existingVal == null) { 
        for (Annotation annotation : writeMethod.getAnnotations()) { 
         if (annotation instanceof AutoInject) { 
          Class propertyType = pd.getPropertyType(); 
          writeMethod.invoke(obj, propertyType.newInstance()); 
         } 
        } 
       } 
      } 
     } catch (Exception e) { 
      // do something intelligent :) 
     } 
     return obj; 
    } 

} 
+0

こんにちは、いいですが、あなたはメインの実際のオブジェクトを渡しています。新しいメインオブジェクトを作成する場合は、そのメソッドを呼び出す必要がありますか?たとえば、Springの注入を見た場合、新しいMain()を実行すると、自動注入(通常はシングルトンオブジェクト)の依存関係が発生します。その考え方は、(スタートアップ時に)すべてのクラスファイルを一度スキャンして、新しいオブジェクトごとにいくつかの動作が追加されるようにすることです。 – momomo

+0

Springはすべてのオブジェクト(ApplicationContext)を作成/配信するためにセントラルコンテキストを使用します。注釈関連コードがどのように機能したかを説明しようとしていたので、私のコードはそうではありません。このメインクラスに結びつけられた注入コードについては何もありません。自分の自作のInjectorクラスに簡単に入れることができます。このクラスは設定を読み込み、オブジェクト作成/サービスの場所を要求します。 – gorjusborg

関連する問題