Java中使用注解的情況主要在SpringMVC(Spring Boot等),注解實際上相當于一種標記語言,它允許你在運行時動態地對擁有該標記的成員進行操作。注意:spring框架默認不支持自動裝配的,要想使用自動裝配需要修改spring配置文件中<bean>標簽的autowire屬性。
自動裝配屬性有6個值可選,分別代表不同的含義:
byName ->從Spring環境中獲取目標對象時,目標對象中的屬性會根據名稱在整個Spring環境中查找<bean>標簽的id屬性值。如果有相同的,那么獲取這個對象,實現關聯。整個Spring環境:表示所有的spring配置文件中查找,那么id不能有重復的。
byType ->從Spring環境中獲取目標對象時,目標對象中的屬性會根據類型在整個spring環境中查找<bean>標簽的class屬性值。如果有相同的,那么獲取這個對象,實現關聯。
缺點:如果存在多個相同類型的bean對象,會出錯;如果屬性為單一類型的數據,那么查找到多個關聯對象會發生錯誤;如果屬性為數組或集合(泛型)類型,那么查找到多個關聯對象不會發生異常。
constructor ->使用構造方法完成對象注入,其實也是根據構造方法的參數類型進行對象查找,相當于采用byType的方式。
autodetect ->自動選擇:如果對象沒有無參數的構造方法,那么自動選擇constructor的自動裝配方式進行構造注入。如果對象含有無參數的構造方法,那么自動選擇byType的自動裝配方式進行setter注入。
no ->不支持自動裝配功能
default ->表示默認采用上一級標簽的自動裝配的取值。如果存在多個配置文件的話,那么每一個配置文件的自動裝配方式都是獨立的。
注解使用需要三個條件包括注解聲明,使用注解的元素,操作使用注解元素的代碼。第一步注解聲明,注解是一種類型,自定義注解編寫代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
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" 默認值為"河北省" } |
使用自定義注解元素,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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函數,具體代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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類中有如下代碼:
1
2
3
4
5
6
7
8
9
|
/** * 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=>
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#processInjection=>
org.springframework.beans.factory.annotation.InjectionMetadata#Injection,查看inject方法源代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/** * 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自動裝配是通過反射機制來實現的。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.yoodb.com/yoodb/article/detail/1310