這篇文章主要為大家詳細介紹了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就是透過這一點,讓操作元素程式碼執行的。
org.springframework.web .context.support.SpringBeanAutowiringSupport#SpringBeanAutowiringSupport=>
org.springframework.web.context.support.SpringBeanAutowiringSupport#processInjectionBasedOnCurrentContext>>>Punywemm. Injection=>
/** * 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(); } } }
以上是Java註解機制實作Spring自動組裝原理的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!