Spring詳細講解@Autowired註解

java註解

在解釋spring的註解之前,先瞭解一下什麼是java的註解?:Java 註解(Annotation)又稱 Java 標註,是 JDK5.0 引入的一種註釋機制。

Java中類、變量、參數、 包等都可以添加註解,java的註解可以通過反射來獲取到標註的內容,在編譯器生成字節碼文件時,標註信息也添加進去。當運行時,JVM可以根據標註信息獲取相應的信息。

先給大傢介紹一下java中常見的7種註解,這種註解也是spring中的註解的基礎!前三個註解是用於代碼上的註解,剩下的四個是用於修飾註解!

  • @Override – 檢查該方法是否是重寫方法。如果發現其父類,或者是引用的接口中並沒有該方法時,會報編譯錯誤。
  • @Deprecated – 標記過時方法。如果使用該方法,會報編譯警告。
  • @SuppressWarnings – 指示編譯器去忽略註解中聲明的警告。
  • @Retention – 標識這個註解怎麼保存,是隻在代碼中,還是編入class文件中,或者是在運行時可以通過反射訪問。
  • @Documented – 標記這些註解是否包含在用戶文檔javadoc中。
  • @Target – 標記這個註解應該是哪種 Java 成員。
  • @Inherited – 標記這個註解是繼承於哪個註解類(默認 註解並沒有繼承於任何子類)

spring註解

然後我們來說一下spring中註解的作用。

spring的重要特征就是控制反轉和依賴註入。在spring中,將部分需要創建和生成的類的控制權限交給瞭spring容器進行管理,這就是控制反轉。依賴註入就是將屬性和類信息註入給相應的類。而這和我們要使用的註解有什麼關系呢?

(1)配置文件形式

我們知道在出現註解之前,spring實現bean的管理是通過配置文件來實現的,所以我們先設計一個簡答的bean來實現一下,如下:結構圖在下面,為瞭方便我把代碼放到瞭一起,實現請對比結構圖!

package com.example.school;
import com.example.studuent.*;
public class chuzhong {
    private lisi Lisi;
    private zhangsan ZhangSan;
    public void setLisi(com.example.studuent.lisi Lisi) {
        this.Lisi = Lisi;
    }
    public void setZhangsan(com.example.studuent.zhangsan ZhangSan) {
        this.ZhangSan = ZhangSan;
    }
    public com.example.studuent.lisi getLisi() {
        return Lisi;
    }
    public com.example.studuent.zhangsan getZhangsan() {
        return ZhangSan;
    }
    public String toString()
    {
        return Lisi.name;
    }
}
package com.example.studuent;
public class lisi {
    public String name = "李四";
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public String studentname(){
        return name;
    }
}
package com.example.studuent;
public class zhangsan {
    public String name = "張三";
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public String studentname(){
        return "這個學生是:" + name;
    }
}
import com.example.school.*;
import com.example.studuent.lisi;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class annotationExample {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        chuzhong cz = (chuzhong) context.getBean("chuzhong");
        String name = cz.getLisi().studentname();
        System.out.println(name);
    }
}

配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        <bean id="chuzhong" class="com.example.school.chuzhong" >
            <property name="lisi" ref="lisi" />
            <property name="zhangsan" ref="zhangsan" />
        </bean>
        <bean id="lisi" class="com.example.studuent.lisi" />
        <bean id="zhangsan" class="com.example.studuent.zhangsan" />
</beans>

運行結果:

可以看到,加載瞭相應的配置文件,然後spring容器依次創建瞭相應的實例對象。並成功輸出的lisi實例對象的姓名。

這就是未使用註解時候,bean的使用方法。

(2)註解形式

加入瞭註解之後,我們會省下配置很多不必要信息的時間。最常用的自動裝配的註解@Autowired,用於放置在類上用來修飾。

可以瞭解一下@Autowired的源碼中的註解信息,咱們簡單看一個重要的信息

這個說,構造函數、字段、setter方法或config方法標記為由Spring的依賴項註入工具自動連接。

而@Autowired這個註解對應的,就是我們在chuzhong類中,寫的set和get方法,以及配置文件中的property標簽的內容,它可以幫我們自動關聯bean對象,實現自動裝配功能。

所以我們使用@Autowired註解之後的類文件和配置文件就變成瞭如下圖,關聯的zhangsan和lisi類對象的set和get方法省略,並且配置文件中property中內容省略,但是需要加上component-scan組件掃描配置,因為當出現@Autowired註解之後,會從base-package下查找相應的關聯bean對象:

@Autowired的解析

我們來分析一下@Autowired中都是什麼東西:

1,首先註解是使用@interface修飾的,意味著它實現瞭 java.lang.annotation.Annotation 接口,使用@interface修飾才可以生成註解的形式

2,綠色字體的意思,註解依賴是否是必須的,也就是你使用瞭@Autowired這個註解,那麼可以手動配置required,是否使用,默認是寫瞭該註解就是使用

3,我們在文章第一段說明瞭,有四個註解是用來修飾註解的。我用一段來解釋一下其中字段的意思。

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) 表示這個註解是用來修改哪種成員的,如果沒有寫這個@Target則表示,它可以用在任何地方。然後我們瞭解一下ElementType這個枚舉類中中各個字段的意思。從下面我們可以看出,它可以修飾構造器、方法、參數、成員變量以及註解。所以多個ElementType對應一個註解。

TYPE:                 能修飾類、接口或枚舉類型
FIELD:                能修飾成員變量
METHOD:               能修飾方法
PARAMETER:            能修飾參數
CONSTRUCTOR:          能修飾構造器
LOCAL_VARIABLE:       能修飾局部變量
ANNOTATION_TYPE:      能修飾註解
PACKAGE:              能修飾包
TYPE_PARAMETER:       能修飾類型參數
TYPE_USE:             所有類型都可以修飾(不包括類)

@Retention(RetentionPolicy.RUNTIME)用於指定該註解的生命周期,存活到什麼時候,RUNTIME表明存活到運行時,可以反射獲取相應的信息。

SOURCE:該註解存在於源碼中,當編譯成字節碼時,就消失瞭。
CLASS: 該註解在java文件生成字節碼文件後,存在於字節中,但是在jvm運行中就沒瞭。@Retention的默認值,即當沒有顯式指定@Retention的時候,就會是這種類型。
RUNTIME: 該標註信息存在字節碼中,jvm運行該字節碼時,可以通過標註獲取相應的信息

@Documented文中第一段有說明。

@Autowired的生效流程

而@Autowired是如何生效的呢?我引用一下別人的文章:SpringBoot中@Autowired是如何生效的,希望大傢也可以看一看,我摘重點說一下。下圖就是spring啟動之後的流程。

首先是AutowiredPorcessor的BeanDefinition的註冊

1, 創建ApplicationContext

2, 創建AnnotatedBeanDefinitionReader

3, 註冊BeanDefinition registerAnnotationConfigProcessors

然後是AutowiredProcessor註冊為bean

1,registerBeanPostProcessors

最後是註入

1,獲取bean getBean()

2,創建bean doCreateBean()

​3,生成bean populateBean()

4,應用AutowiredProcessor ibp.postProcessProperties()

5,找到可註入的字段 buildAutowiringMetadata

6,註入 metadata.inject

spring的其餘註解也可以參考這種形式,逐一進行分析,個人的註解放到(二)中實現。

到此這篇關於spring詳細講解@Autowired註解的解析的文章就介紹到這瞭,更多相關spring @Autowired內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: