Java注釈とSpringの@Autowiredがどうやって実現されているかを理解します。


まず自分で注釈を書いてもいいです。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoSample {
    String value();
}
注釈は@interfaceを使用して識別される。この注釈は一つの属性valueを定義しています。方法でしか使えないです。ライフサイクルは運行時です。
@Targetは注釈を置くことができる位置を指定します。ここで指定されたMETHODは方法の上にしか置かないと説明しています。TYPE(クラス、インターフェース、エニュメレーション類)、FIELDの例、PAAMETER形参、CONSTRUCTORコンフォメーションなども指定できます。
注解のライフサイクルを定義するために使われています。SOURCEはコンパイル中に廃棄されます。コンパイルが完了した後、これらの注釈は何の意味もありません。CLASSクラスのローディング中に破棄されるのは、標準値です。RUNTIMEは破棄されません。運転中に反射して取得できます。
じゃ、この注を使います。

public class HelloWorld {
    
    @AnnoSample(value = "hello")
    public void hello(){
        System.out.println("hello,world");
    }
}
ここで注解を作成して使用します。すでに完了しました。
しかし、この注釈は何の変化も持って来ていないことが分かります。この注釈があるとないとの違いは大きくないです。では、注釈自体はメタデータとしてしか見なされないことを知る必要があります。業務ロジックは一切含まれていません。注釈はさらにラベルのようになり、表が注釈されているこの場所には、特定の論理がある。
この方法にはラベルがあります。ここに行って論理をつけるべきだということを教えてください。このラベルはどうやって取得しますか?
反射が使えます。
  • 反射機構を利用してクラスのクラスのクラスのオブジェクトを取得することができます。このクラスのオブジェクトを通じて、彼を取得することができます。
  •  method、またはフィールドFieldなどのMethod、Fieldなどのクラスは、このフィールドまたは方法のすべての注釈を取得するためのget Annotation()と同様の方法を提供する。
  • は注釈を取ってから、この注釈が私達が実現する注釈かどうかを判断できます。もしそうであれば、注釈論理
  • を実現します。
    具体的な実現は以下の通りです。
    
    public class Main {
        public static void main(String[] args) throws Exception {
            Class c=Class.forName("HelloWorld");
            Method[] methods = c.getMethods();
            for (Method method : methods) {
                Annotation[] annotations = method.getDeclaredAnnotations();
                for (Annotation annotation : annotations) {
                    if (annotation.annotationType()==AnnoSample.class) {
                        System.out.println(((AnnoSample)annotation).value());
                    }
                }
            }
        }
    }
    上記のコードは、反射によって前に書いたHelloWorldクラスのMethod配列を取得し、巡回し、各方法のすべての注釈を遍歴して、もし私たちが判断する注釈が必要なif (annotation.annotationType()==AnnoSample.class)が見つかったら、いくつかの論理処理を行います。ここではvalueの値を印刷します。
    注解の基礎知識が分かりましたので、Springの@Autowiredはどうやって実現されたのか見に行きます。
    @Autowired
    ソースコードを見てください:
    
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Autowired {
    
    	/**
    	 * Declares whether the annotated dependency is required.
    	 * <p>Defaults to {@code true}.
    	 */
    	boolean required() default true;
    
    }
    解読してみると、この注釈はコンストラクタ、実例的な方法、モジュラス、実例的な変数、注釈に用いられ、ライフサイクルは実行時である。ここの@DcumentedはJava docに注釈を追加するかどうかを示すだけです。
    @Autowired注釈自体は特に何もないことが分かります。重要なのはこの注釈に関する特定のロジックです。
    ロジックのクラスはソースの上にヒントがあります。
    在这里插入图片描述
    このクラスについては、Shiftを使用して2回連続でグローバル検索を行う。buildAutowiringMetadata()の方法は論理的なものである。
    在这里插入图片描述
    最初の矢印は現在のクラスを得て、そして第二の矢印はtargetClassの中のすべてのfiledを判断して、@Autowiredがあるかどうかを確認することです。以下のdoWithLocalMethodsはここでfiledが似ていると判断します。
    @Autowiredで判断した後、次のように実行します。
    
    currElements.add(new AutowiredFieldElement(field, required));
    このフィールドをコンテナに入れます。@Autowiredを使った例示的な変数/方法は一つしかないので、全部探して判断します。
    この方法の最後に:
    在这里插入图片描述
    このクラスと@Autowired注釈を使用した実例的なセットを返します。戻ってきたのはこれです。次のステップはそれを注入することです。
    注入ロジックはpostProcessProperties()方法である。
    在这里插入图片描述
    この方法の最初の一つは、findAutowiringMetadata()方法を呼び出すことであり、その後、この方法では、私たちの前で解析したbuildAutowiringMetadata()を呼び出し、つまり、クラスとその注釈情報を得て、次のinject()方法で注入を開始することである。
    在这里插入图片描述
    フィールドに対して、反射クラスFieldのset()メソッド設定値を呼び出します。
    
    field.set(target, getResourceToInject(target, requestingBeanName));
    方法については、invokeを用いて具体的なパラメータ値を持ち込んで実行する。
    
    method.invoke(target, getResourceToInject(target, requestingBeanName));
    getResourceToInject()メソッドのパラメータは、注入されるbeanの名前であり、この方法の機能は、このbeanの名前に基づいて取得することである。
    ここで、Javaの注釈とSpringの@Autowiredがどのように実現されているかを理解する記事を紹介します。javaの注釈Springの@Autowiredの内容については、以前の文章を検索したり、下記の関連記事を引き続き閲覧したりしてください。これからもよろしくお願いします。