国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - 徹底搞明白Spring中的自動裝配和Autowired注解的使用

徹底搞明白Spring中的自動裝配和Autowired注解的使用

2021-07-22 15:42清幽之地 Java教程

這篇文章主要介紹了徹底搞明白Spring中的自動裝配和Autowired注解的使用,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

一、自動裝配

當spring裝配bean屬性時,有時候非常明確,就是需要將某個bean的引用裝配給指定屬性。比如,如果我們的應用上下文中只有一個org.mybatis.spring.sqlsessionfactorybean類型的bean,那么任意一個依賴sqlsessionfactorybean的其他bean就是需要這個bean。畢竟這里只有一個sqlsessionfactorybean的bean。

為了應對這種明確的裝配場景,spring提供了自動裝配(autowiring)。與其顯式的裝配bean屬性,為何不讓spring識別出可以自動裝配的場景。

當涉及到自動裝配bean的依賴關系時,spring有多種處理方式。因此,spring提供了4種自動裝配策略。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface autowirecapablebeanfactory{
 
 //無需自動裝配
 int autowire_no = 0;
 
 //按名稱自動裝配bean屬性
 int autowire_by_name = 1;
 
 //按類型自動裝配bean屬性
 int autowire_by_type = 2;
 
 //按構造器自動裝配
 int autowire_constructor = 3;
 
 //過時方法,spring3.0之后不再支持
 @deprecated
 int autowire_autodetect = 4;
}

spring在autowirecapablebeanfactory接口中定義了這幾種策略。其中,autowire_autodetect被標記為過時方法,在spring3.0之后已經不再支持。

1、byname

它的意思是,把與bean的屬性具有相同名字的其他bean自動裝配到bean的對應屬性中。聽起來可能比較拗口,我們來看個例子。

首先,在user的bean中有個屬性role myrole,再創建一個role的bean,它的名字如果叫myrole,那么在user中就可以使用byname來自動裝配。

?
1
2
3
4
5
6
7
public class user{
 private role myrole;
}
public class role {
 private string id;
 private string name;
}

上面是bean的定義,再看配置文件。

?
1
2
3
4
5
6
<bean id="myrole" class="com.viewscenes.netsupervisor.entity.role">
 <property name="id" value="1001"></property>
 <property name="name" value="管理員"></property>
</bean>
 
<bean id="user" class="com.viewscenes.netsupervisor.entity.user" autowire="byname"></bean>

如上所述,只要屬性名稱和bean的名稱可以對應,那么在user的bean中就可以使用byname來自動裝配。那么,如果屬性名稱對應不上呢?

2、bytype

是的,如果不使用屬性名稱來對應,你也可以選擇使用類型來自動裝配。它的意思是,把與bean的屬性具有相同類型的其他bean自動裝配到bean的對應屬性中。

?
1
2
3
4
5
6
<bean class="com.viewscenes.netsupervisor.entity.role">
 <property name="id" value="1001"></property>
 <property name="name" value="管理員"></property>
</bean>
 
<bean id="user" class="com.viewscenes.netsupervisor.entity.user" autowire="bytype"></bean>

還是上面的例子,如果使用bytype,role bean的id都可以省去。

3、constructor

它是說,把與bean的構造器入參具有相同類型的其他bean自動裝配到bean構造器的對應入參中。值的注意的是,具有相同類型的其他bean這句話說明它在查找入參的時候,還是通過bean的類型來確定。
構造器中入參的類型為role

?
1
2
3
4
5
6
7
8
9
public class user{
 private role role;
 
 public user(role role) {
 this.role = role;
 }
}
 
<bean id="user" class="com.viewscenes.netsupervisor.entity.user" autowire="constructor"></bean>

4、autodetect

它首先會嘗試使用constructor進行自動裝配,如果失敗再嘗試使用bytype。不過,它在spring3.0之后已經被標記為@deprecated。

5、默認自動裝配

默認情況下,default-autowire屬性被設置為none,標示所有的bean都不使用自動裝配,除非bean上配置了autowire屬性。
如果你需要為所有的bean配置相同的autowire屬性,有個辦法可以簡化這一操作。

在根元素beans上增加屬性default-autowire="bytype"。

?
1
<beans default-autowire="bytype">

spring自動裝配的優點不言而喻。但是事實上,在spring xml配置文件里的自動裝配并不推薦使用,其中筆者認為最大的缺點在于不確定性。或者除非你對整個spring應用中的所有bean的情況了如指掌,不然隨著bean的增多和關系復雜度的上升,情況可能會很糟糕

二、autowired

從spring2.5開始,開始支持使用注解來自動裝配bean的屬性。它允許更細粒度的自動裝配,我們可以選擇性的標注某一個屬性來對其應用自動裝配。

spring支持幾種不同的應用于自動裝配的注解。

  • spring自帶的@autowired注解。
  • jsr-330的@inject注解。
  • jsr-250的@resource注解。

我們今天只重點關注autowired注解,關于它的解析和注入過程,請參考筆者spring源碼系列的文章。spring源碼分析(二)bean的實例化和ioc依賴注入

使用@autowired很簡單,在需要注入的屬性加入注解即可。

?
1
2
@autowired
userservice userservice;

不過,使用它有幾個點需要注意。

1、強制性

默認情況下,它具有強制契約特性,其所標注的屬性必須是可裝配的。如果沒有bean可以裝配到autowired所標注的屬性或參數中,那么你會看到nosuchbeandefinitionexception的異常信息。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public object doresolvedependency(dependencydescriptor descriptor, string beanname,
  set<string> autowiredbeannames, typeconverter typeconverter) throws beansexception {
 
 //查找bean
 map<string, object> matchingbeans = findautowirecandidates(beanname, type, descriptor);
 //如果拿到的bean集合為空,且isrequired,就拋出異常。
 if (matchingbeans.isempty()) {
 if (descriptor.isrequired()) {
  raisenosuchbeandefinitionexception(type, "", descriptor);
 }
 return null;
 }
}

看到上面的源碼,我們可以得到這一信息,bean集合為空不要緊,關鍵isrequired條件不能成立,那么,如果我們不確定屬性是否可以裝配,可以這樣來使用autowired。

?
1
2
@autowired(required=false)
userservice userservice;

2、裝配策略

我記得曾經有個面試題是這樣問的:autowired是按照什么策略來自動裝配的呢?
關于這個問題,不能一概而論,你不能簡單的說按照類型或者按照名稱。但可以確定的一點的是,它默認是按照類型來自動裝配的,即bytype。

默認按照類型裝配

關鍵點findautowirecandidates這個方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected map<string, object> findautowirecandidates(
 string beanname, class<?> requiredtype, dependencydescriptor descriptor) {
 
 //獲取給定類型的所有bean名稱,里面實際循環所有的beanname,獲取它的實例
 //再通過istypematch方法來確定
 string[] candidatenames = beanfactoryutils.beannamesfortypeincludingancestors(
  this, requiredtype, true, descriptor.iseager());
  
 map<string, object> result = new linkedhashmap<string, object>(candidatenames.length);
 
 //根據返回的beanname,獲取其實例返回
 for (string candidatename : candidatenames) {
 if (!isselfreference(beanname, candidatename) && isautowirecandidate(candidatename, descriptor)) {
  result.put(candidatename, getbean(candidatename));
 }
 }
 return result;
}

按照名稱裝配

可以看到它返回的是一個列表,那么就表明,按照類型匹配可能會查詢到多個實例。到底應該裝配哪個實例呢?我看有的文章里說,可以加注解以此規避。比如@qulifier、@primary等,實際還有個簡單的辦法。

比如,按照userservice接口類型來裝配它的實現類。userservice接口有多個實現類,分為userserviceimpl、userserviceimpl2。那么我們在注入的時候,就可以把屬性名稱定義為bean實現類的名稱。

?
1
2
@autowired
userservice userserviceimpl2;

這樣的話,spring會按照byname來進行裝配。首先,如果查到類型的多個實例,spring已經做了判斷。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public object doresolvedependency(dependencydescriptor descriptor, string beanname,
  set<string> autowiredbeannames, typeconverter typeconverter) throws beansexception {
  
 //按照類型查找bean實例
 map<string, object> matchingbeans = findautowirecandidates(beanname, type, descriptor);
 //如果bean集合為空,且isrequired成立就拋出異常
 if (matchingbeans.isempty()) {
 if (descriptor.isrequired()) {
  raisenosuchbeandefinitionexception(type, "", descriptor);
 }
 return null;
 }
 //如果查找的bean實例大于1個
 if (matchingbeans.size() > 1) {
 //找到最合適的那個,如果沒有合適的。。也拋出異常
 string primarybeanname = determineautowirecandidate(matchingbeans, descriptor);
 if (primarybeanname == null) {
  throw new nouniquebeandefinitionexception(type, matchingbeans.keyset());
 }
 if (autowiredbeannames != null) {
  autowiredbeannames.add(primarybeanname);
 }
 return matchingbeans.get(primarybeanname);
 }
}

可以看出,如果查到多個實例,determineautowirecandidate方法就是關鍵。它來確定一個合適的bean返回。其中一部分就是按照bean的名稱來匹配。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
protected string determineautowirecandidate(map<string, object> candidatebeans,
  dependencydescriptor descriptor) {
 //循環拿到的bean集合
 for (map.entry<string, object> entry : candidatebeans.entryset()) {
 string candidatebeanname = entry.getkey();
 object beaninstance = entry.getvalue();
 //通過matchesbeanname方法來確定bean集合中的名稱是否與屬性的名稱相同
 if (matchesbeanname(candidatebeanname, descriptor.getdependencyname())) {
  return candidatebeanname;
 }
 }
 return null;
}

最后我們回到問題上,得到的答案就是:@autowired默認使用bytype來裝配屬性,如果匹配到類型的多個實例,再通過byname來確定bean。

3、主和優先級

上面我們已經看到了,通過bytype可能會找到多個實例的bean。然后再通過byname來確定一個合適的bean,如果通過名稱也確定不了呢?

還是determineautowirecandidate這個方法,它還有兩種方式來確定。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protected string determineautowirecandidate(map<string, object> candidatebeans,
  dependencydescriptor descriptor) {
 class<?> requiredtype = descriptor.getdependencytype();
 //通過@primary注解來標識bean
 string primarycandidate = determineprimarycandidate(candidatebeans, requiredtype);
 if (primarycandidate != null) {
 return primarycandidate;
 }
 //通過@priority(value = 0)注解來標識bean value為優先級大小
 string prioritycandidate = determinehighestprioritycandidate(candidatebeans, requiredtype);
 if (prioritycandidate != null) {
 return prioritycandidate;
 }
 return null;
}

primary

它的作用是看bean上是否包含@primary注解,如果包含就返回。當然了,你不能把多個bean都設置為@primary,不然你會得到nouniquebeandefinitionexception這個異常。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected string determineprimarycandidate(map<string, object> candidatebeans, class<?> requiredtype) {
 string primarybeanname = null;
 for (map.entry<string, object> entry : candidatebeans.entryset()) {
 string candidatebeanname = entry.getkey();
 object beaninstance = entry.getvalue();
 if (isprimary(candidatebeanname, beaninstance)) {
  if (primarybeanname != null) {
  boolean candidatelocal = containsbeandefinition(candidatebeanname);
  boolean primarylocal = containsbeandefinition(primarybeanname);
  if (candidatelocal && primarylocal) {
   throw new nouniquebeandefinitionexception(requiredtype, candidatebeans.size(),
    "more than one 'primary' bean found among candidates: " + candidatebeans.keyset());
  }
  else if (candidatelocal) {
   primarybeanname = candidatebeanname;
  }
  }
  else {
  primarybeanname = candidatebeanname;
  }
 }
 }
 return primarybeanname;
}

priority

你也可以在bean上配置@priority注解,它有個int類型的屬性value,可以配置優先級大小。數字越小的,就被優先匹配。同樣的,你也不能把多個bean的優先級配置成相同大小的數值,否則nouniquebeandefinitionexception異常照樣出來找你。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
protected string determinehighestprioritycandidate(map<string, object> candidatebeans,
     class<?> requiredtype) {
 string highestprioritybeanname = null;
 integer highestpriority = null;
 for (map.entry<string, object> entry : candidatebeans.entryset()) {
 string candidatebeanname = entry.getkey();
 object beaninstance = entry.getvalue();
 integer candidatepriority = getpriority(beaninstance);
 if (candidatepriority != null) {
  if (highestprioritybeanname != null) {
  //如果優先級大小相同
  if (candidatepriority.equals(highestpriority)) {
   throw new nouniquebeandefinitionexception(requiredtype, candidatebeans.size(),
   "multiple beans found with the same priority ('" + highestpriority + "') " +
    "among candidates: " + candidatebeans.keyset());
  }
  else if (candidatepriority < highestpriority) {
   highestprioritybeanname = candidatebeanname;
   highestpriority = candidatepriority;
  }
  }
  else {
  highestprioritybeanname = candidatebeanname;
  highestpriority = candidatepriority;
  }
 }
 }
 return highestprioritybeanname;
}

最后,有一點需要注意。priority的包在javax.annotation.priority;,如果想使用它還要引入一個坐標。

?
1
2
3
4
5
<dependency>
 <groupid>javax.annotation</groupid>
 <artifactid>javax.annotation-api</artifactid>
 <version>1.2</version>
</dependency>

三、總結

本章節重點闡述了spring中的自動裝配的幾種策略,又通過源碼分析了autowired注解的使用方式。

在spring3.0之后,有效的自動裝配策略分為bytype、byname、constructor三種方式。注解autowired默認使用bytype來自動裝配,如果存在類型的多個實例就嘗試使用byname匹配,如果通過byname也確定不了,可以通過primary和priority注解來確定。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://juejin.im/post/5c84b5285188257c5b477177

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 午夜视频在线 | 视频三区 | 国产在线专区 | 亚洲国产精品久久人人爱 | 成人在线视频免费观看 | 欧美在线一区二区三区 | 中文在线视频 | av免费网站在线观看 | 亚洲四区 | av在线天堂 | 天堂俺去俺来也www久久婷婷 | 欧美综合国产 | 午夜影院在线观看 | 99热最新网址 | 91色在线观看 | 欧美一区二区在线播放 | a级在线免费观看 | 国精产品99永久一区一区 | 亚洲一区二区三区在线播放 | 中文字幕国产一区二区 | 极品久久| 成人国产精品久久 | 亚洲精品一区二区三区在线观看 | 亚洲高清在线 | 久久一二区 | 男人久久久 | 亚洲国产视频一区二区 | 特黄特色一级片 | 国产一区二区三区视频在线观看 | 婷婷色av| 91中文字幕在线 | 国产乱淫精品一区二区三区毛片 | 国产一区二区三区在线视频观看 | 一本大道综合伊人精品热热 | 国产精品久久久久久久午夜片 | 4h影院 | 高清av在线| 色九九| 中文字幕高清视频 | 福利在线看 | 亚洲激情一区 |