日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java的注解机制——Spring自动装配的实现原理

發(fā)布時(shí)間:2023/11/30 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java的注解机制——Spring自动装配的实现原理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  JDK1.5加入了對(duì)注解機(jī)制的支持,實(shí)際上我學(xué)習(xí)Java的時(shí)候就已經(jīng)使用JDK1.6了,而且除了@Override和@SuppressWarnings(后者還是IDE給生成的……)之外沒接觸過其他的。

  進(jìn)入公司前的面試,技術(shù)人員就問了我關(guān)于注解的問題,我就說可以生成chm手冊(cè)……現(xiàn)在想起來真囧,注釋和注解被我搞得完全一樣了。

  

  使用注解主要是在需要使用Spring框架的時(shí)候,特別是使用SpringMVC。因?yàn)檫@時(shí)我們會(huì)發(fā)現(xiàn)它的強(qiáng)大之處:預(yù)處理。

  注解實(shí)際上相當(dāng)于一種標(biāo)記,它允許你在運(yùn)行時(shí)(源碼、文檔、類文件我們就不討論了)動(dòng)態(tài)地對(duì)擁有該標(biāo)記的成員進(jìn)行操作。

  實(shí)現(xiàn)注解需要三個(gè)條件(我們討論的是類似于Spring自動(dòng)裝配的高級(jí)應(yīng)用):注解聲明、使用注解的元素、操作使用注解元素的代碼

  

  首先是注解聲明,注解也是一種類型,我們要定義的話也需要編寫代碼,如下:

1 package annotation; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 /** 9 * 自定義注解,用來配置方法 10 * 11 * @author Johness 12 * 13 */ 14 @Retention(RetentionPolicy.RUNTIME) // 表示注解在運(yùn)行時(shí)依然存在 15 @Target(ElementType.METHOD) // 表示注解可以被使用于方法上 16 public @interface SayHiAnnotation { 17 String paramValue() default "johness"; // 表示我的注解需要一個(gè)參數(shù) 名為"paramValue" 默認(rèn)值為"johness" 18 }

?

  然后是使用我們注解的元素:

1 package element; 2 3 import annotation.SayHiAnnotation; 4 5 /** 6 * 要使用SayHiAnnotation的元素所在類 7 * 由于我們定義了只有方法才能使用我們的注解,我們就使用多個(gè)方法來進(jìn)行測(cè)試 8 * 9 * @author Johness 10 * 11 */ 12 public class SayHiEmlement { 13 14 // 普通的方法 15 public void SayHiDefault(String name){ 16 System.out.println("Hi, " + name); 17 } 18 19 // 使用注解并傳入?yún)?shù)的方法 20 @SayHiAnnotation(paramValue="Jack") 21 public void SayHiAnnotation(String name){ 22 System.out.println("Hi, " + name); 23 } 24 25 // 使用注解并使用默認(rèn)參數(shù)的方法 26 @SayHiAnnotation 27 public void SayHiAnnotationDefault(String name){ 28 System.out.println("Hi, " + name); 29 } 30 }

  最后,是我們的操作方法(值得一提的是雖然有一定的規(guī)范,但您大可不必去浪費(fèi)精力,您只需要保證您的操作代碼在您希望的時(shí)候執(zhí)行即可):

1 package Main; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 6 import element.SayHiEmlement; 7 import annotation.SayHiAnnotation; 8 9 public class AnnotionOperator { 10 public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException { 11 SayHiEmlement element = new SayHiEmlement(); // 初始化一個(gè)實(shí)例,用于方法調(diào)用 12 Method[] methods = SayHiEmlement.class.getDeclaredMethods(); // 獲得所有方法 13 14 for (Method method : methods) { 15 SayHiAnnotation annotationTmp = null; 16 if((annotationTmp = method.getAnnotation(SayHiAnnotation.class))!=null) // 檢測(cè)是否使用了我們的注解 17 method.invoke(element,annotationTmp.paramValue()); // 如果使用了我們的注解,我們就把注解里的"paramValue"參數(shù)值作為方法參數(shù)來調(diào)用方法 18 else 19 method.invoke(element, "Rose"); // 如果沒有使用我們的注解,我們就需要使用普通的方式來調(diào)用方法了 20 } 21 } 22 }

  結(jié)果為:Hi, Jack
      Hi, johness
      Hi, Rose

  可以看到,注解是進(jìn)行預(yù)處理的很好方式(這里的預(yù)處理和編譯原理有區(qū)別)!

?

  接下來我們看看Spring是如何使用注解機(jī)制完成自動(dòng)裝配的:

  

    首先是為了讓Spring為我們自動(dòng)裝配要進(jìn)行的操作,無外乎兩種:繼承org.springframework.web.context.support.SpringBeanAutowiringSupport類或者添加@Component/@Controller等注解并(只是使用注解方式需要)在Spring配置文件里聲明context:component-scan元素。

    我說說繼承方式是如何實(shí)現(xiàn)自動(dòng)裝配的,我們打開Spring源代碼查看SpringBeanAutowiringSupport類。我們會(huì)發(fā)現(xiàn)以下語句:

1 public SpringBeanAutowiringSupport() { 2 processInjectionBasedOnCurrentContext(this); 3 }

?

    眾所周知,Java實(shí)例構(gòu)造時(shí)會(huì)調(diào)用默認(rèn)父類無參構(gòu)造方法,Spring正是利用了這一點(diǎn),讓"操作元素的代碼"得以執(zhí)行!(我看到第一眼就震驚了!真是奇思妙想啊。果然,高手都要善于用Java來用Java)

    后面的我就不就不多說了,不過還是要糾正一些人的觀點(diǎn):說使用注解的自動(dòng)裝配來完成注入也需要setter。這明顯是錯(cuò)誤的嘛!我們看Spring注解裝配(繼承方式)的方法調(diào)用順序:?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(繼承,方法重寫)。最后看看Injection方法的方法體:

1 /** 2 * Either this or {@link #getResourceToInject} needs to be overridden. 3 */ 4 protected void inject(Object target, String requestingBeanName, PropertyValues pvs) throws Throwable { 5 if (this.isField) { 6 Field field = (Field) this.member; 7 ReflectionUtils.makeAccessible(field); 8 field.set(target, getResourceToInject(target, requestingBeanName)); 9 } 10 else { 11 if (checkPropertySkipping(pvs)) { 12 return; 13 } 14 try { 15 Method method = (Method) this.member; 16 ReflectionUtils.makeAccessible(method); 17 method.invoke(target, getResourceToInject(target, requestingBeanName)); 18 } 19 catch (InvocationTargetException ex) { 20 throw ex.getTargetException(); 21 } 22 } 23 }

      雖然不完全,但可以基本判定此種自動(dòng)裝配是使用了java放射機(jī)制。

?

?歡迎您移步我們的交流群,無聊的時(shí)候大家一起打發(fā)時(shí)間:

?或者通過QQ與我聯(lián)系:

?(最后編輯時(shí)間2013-04-19 09:52:27)

?

轉(zhuǎn)載于:https://www.cnblogs.com/Johness/archive/2013/04/17/3026689.html

總結(jié)

以上是生活随笔為你收集整理的Java的注解机制——Spring自动装配的实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。