首頁 >Java >java教程 >Java註解機制實作Spring自動組裝原理的詳解

Java註解機制實作Spring自動組裝原理的詳解

黄舟
黄舟原創
2017-10-18 10:06:162336瀏覽

這篇文章主要為大家詳細介紹了Java註解機制之Spring自動組裝實作原理,具有一定的參考價值,有興趣的小夥伴們可以參考一下

 Java中使用註解的情況主要在SpringMVC(Spring Boot等),註解實際上相當於一種標記語言,它允許你在運行時動態地對擁有該標記的成員進行操作。注意:spring框架預設不支援自動組裝的,若要使用自動組裝需要修改spring設定檔中60e23eb984d18edbb092da6b8f295aba標籤的autowire屬性。

自動組裝屬性有6個值可選,分別代表不同的意義:

byName ->從Spring環境中取得目標物件時,目標物件中的屬性會根據名稱在整個Spring環境中尋找60e23eb984d18edbb092da6b8f295aba標籤的id屬性值。如果有相同的,那麼取得這個對象,實現關聯。整個Spring環境:表示所有的spring設定檔中查找,那麼id不能有重複的。 

byType ->從Spring環境中取得目標物件時,目標物件中的屬性會根據類型在整個spring環境中尋找60e23eb984d18edbb092da6b8f295aba標籤的class屬性值。如果有相同的,那麼取得這個對象,實現關聯。

缺點:如果存在多個相同類型的bean對象,會出錯;如果屬性為單一類型的數據,那麼查找到多個關聯對象會發生錯誤;如果屬性為數組或集合(泛型)類型,那麼查找到多個關聯物件不會發生異常。

constructor ->使用建構方法完成物件注入,其實也是根據建構方法的參數型別進行物件查找,相當於採用byType的方式。

autodetect ->自動選擇:如果物件沒有無參數的建構方法,那麼自動選擇constructor的自動組裝方式進行建構注入。如果物件含有無參數的建構方法,那麼自動選擇byType的自動組裝方式進行setter注入。                    ‧如果存在多個設定檔的話,那麼每一個設定檔的自動組裝方式都是獨立的。

註解使用需要三個條件包括註解聲明,使用註解的元素,操作使用註解元素的程式碼。第一步註解聲明,註解是一種類型,自訂註解編寫程式碼如下:


#
package annotation;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AttachAnnotation {
  String paramValue() default "河北省"; // 参数名为"paramValue" 默认值为"河北省"
}

使用自訂註解元素,程式碼如下:


package annotation;

/**
 * @author 路人宅
 */
public class AttachEmlement {

  // 普通
  public void AttachDefault(String name){
    System.out.println("归属:" + name);
  }
  
  // 使用注解并传入参数
  @AttachAnnotation(paramValue="河北省")
  public void AttachAnnotation(String name){
    System.out.println("归属:" + name);
  }
  
  // 使用注解并使用默认参数
  @AttachAnnotation
  public void AttachAnnotationDefault(String name){
    System.out.println("归属:" + name);
  }
}

測試操作執行main函數,具體程式碼如下:


package annotation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class AnnotionOperator {
 public static void main(String[] args) throws IllegalAccessException,
  IllegalArgumentException, InvocationTargetException,
  ClassNotFoundException {
 AttachEmlement element = new AttachEmlement(); // 初始化一个实例,用于方法调用
 Method[] methods = AttachEmlement.class.getDeclaredMethods(); // 获得所有方法

 for (Method method : methods) {
  AttachAnnotation annotationTmp = null;
  if ((annotationTmp = method.getAnnotation(AttachAnnotation.class)) != null)
  method.invoke(element, annotationTmp.paramValue());
  else
  method.invoke(element, "河南省");
 }
 }
}

執行結果:

歸屬: 河南省
歸屬:河北省

歸屬:河北省


Spring為了方便自動裝配進行操作有兩種方式:繼承org.springframework.web. context.support.SpringBeanAutowiringSupport類別或新增@Component/@Controller等註解並在Spring設定檔裡聲明context:component-scan元素配置。


1) 繼承方式實作自動裝配,查看Spring3.1.1原始程式碼會發現SpringBeanAutowiringSupport類別中有以下程式碼:


#
/**
 * This constructor performs injection on this instance,
 * based on the current web application context.
 * Intended for use as a base class.
 * @see #processInjectionBasedOnCurrentContext
 */
public SpringBeanAutowiringSupport() {
 processInjectionBasedOnCurrentContext(this);
}

分析:Java在實例化建構時會呼叫預設父類別無參構造方法,而Spring就是透過這一點,讓操作元素程式碼執行的。

2) 透過註解方式的也和上述理論相似,值得注意的是註解自動組裝無需完成註入setter*,查看Spring3.1.1源碼註解調用順序得出:

org.springframework.web .context.support.SpringBeanAutowiringSupport#SpringBeanAutowiringSupport=>
org.springframework.web.context.support.SpringBeanAutowiringSupport#processInjectionBasedOnCurrentContext>>>Pun​​ywem​​m. Injection=>

org.springframework.beans.factory.annotation.InjectionMetadata#Injection,查看inject方法原始碼如下:



/**
 * Either this or {@link #getResourceToInject} needs to be overridden.
 */
protected void inject(Object target, String requestingBeanName, PropertyValues pvs) throws Throwable {
 if (this.isField) {
 Field field = (Field) this.member;
 ReflectionUtils.makeAccessible(field);
 field.set(target, getResourceToInject(target, requestingBeanName));
 }
 else {
 if (checkPropertySkipping(pvs)) {
  return;
 }
 try {
  Method method = (Method) this.member;
  ReflectionUtils.makeAccessible(method);
  method.invoke(target, getResourceToInject(target, requestingBeanName));
 }
 catch (InvocationTargetException ex) {
  throw ex.getTargetException();
 }
 }
}

分析:透過上述原始碼Spring自動組裝是透過反射機制來實現的。

以上是Java註解機制實作Spring自動組裝原理的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn