日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
一個(gè)你可能不曾注意的小東西,Spring依賴注入Bean類型的八種情況

大家好,我是三友~~

創(chuàng)新互聯(lián)建站堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的臨安網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

今天來講的一個(gè)你可能不曾注意的小東西,那就是Spring依賴注入支持注入Bean的類型,這個(gè)小東西可能看似沒有用但是實(shí)際又有點(diǎn)小用。

其實(shí)本來這周沒打算寫文章,但是突然之間就想到了之前有個(gè)妹子問過這個(gè)問題,并且網(wǎng)上這塊東西說的也不多,所以就趕在周末的末尾匆匆寫下了這篇文章。

這東西本身也沒有什么復(fù)雜的原理,所以本文也并沒有什么太多深入剖析源碼的東西。

1、普通對(duì)象

這沒什么好說的,大家都這么用的,比如需要用到UserService,直接@Autowired就可以了。

@Autowired
private UserService userService;

2、Collection及其子接口

除了支持注入一個(gè)單一的對(duì)象之外,@Autowired還支持注入一個(gè)Collection對(duì)象。

比如說,現(xiàn)在有個(gè)消息通知的接口MessageNotifier。

這種接口一般都會(huì)有不同的實(shí)現(xiàn),比如說通過郵件通知,或者app,短信等等,所以就有多種實(shí)現(xiàn),此時(shí)如果需要注入MessageNotifier,就可以使用注入Collection的方式,比如

@Autowired
private List messageNotifiers;

不過這種方式有個(gè)規(guī)定,那就是注入的類型必須是Collection及其子接口,如果你直接注入一個(gè)ArrayList,那么此時(shí)是不支持的。

3、數(shù)組

同理,@Autowired可實(shí)現(xiàn)了注入一個(gè)數(shù)組的功能。

@Autowired
private MessageNotifier[] messageNotifiers;

代碼如下:

4、Map

同樣的,@Autowired還可以注入一個(gè)Map。

@Autowired
private Map messageNotifierMap;

此時(shí)注入的map,key的類型就是bean的名稱,這種方式可以配合策略模式使用。

不過,這種方式只支持注入的是Map接口,不支持子類型接口,代碼如下。

5、@Lazy

當(dāng)一個(gè)注入的字段加了@Lazy注解之后,那么此時(shí)就代表這個(gè)字段是延遲注入。

@Autowired
@Lazy
private MessageNotifier messageNotifier;

延遲注入并不是不注入,而是注入目標(biāo)對(duì)象類型的代理對(duì)象,真正的目標(biāo)是當(dāng)需要用到的時(shí)候在創(chuàng)建。

如圖所示,當(dāng)注入的MessageNotifier?時(shí)加了@Lazy注解,那么此時(shí)注入的其實(shí)是MessageNotifier?的代理對(duì)象,而真正的MessageNotifier?對(duì)象并沒有創(chuàng)建,圖中代理對(duì)象我稱為MessageNotifierProxy。

由于注入的是對(duì)象是代理對(duì)象MessageNotifierProxy?,那么真正被使用的就是MessageNotifierProxy?,一旦調(diào)用了MessageNotifierProxy?的方法,此時(shí)MessageNotifierProxy?會(huì)去Spring容器中查找真正的MessageNotifier?對(duì)象,然后再調(diào)用MessageNotifier對(duì)象的方法。

代碼如下:

這就是@Lazy延遲注入的原理。并不是不注入,而是注入一個(gè)代理對(duì)象,可以理解為一個(gè)占位符,一個(gè)空殼子,先占著位置,等用到這個(gè)殼子的時(shí)候,這個(gè)殼子會(huì)去查找到真正的對(duì)象,調(diào)用真正對(duì)象的方法。

@Lazy的一個(gè)使用場(chǎng)景就是用來解決Spring無法處理的循環(huán)依賴場(chǎng)景,比如使用了@Async注解的循環(huán)依賴的場(chǎng)景,不了解的小伙伴可以看一下 @Async注解的坑,小心 這篇文章

6、Optional

Optional是JDK1.8提供的一個(gè)api,可以優(yōu)雅的解決判空的問題。

@Autowired也支持了注入Optional類型。

@Autowired
private Optional messageNotifier;

代碼如下:

注入Optional這種方式可以解決注入的對(duì)象不存在的導(dǎo)致異常問題,也就是安全注入。

比如說,MessageNotifier?這個(gè)對(duì)象Spring容器中并沒有,如果直接注入,此時(shí)會(huì)拋NoSuchBeanDefinitionException異常

而直接通過注入Optional的方式就可以解決這個(gè)問題。

除了通過Optional的方式之外,也可以直接把@Autowired的required的屬性設(shè)置為false來解決注入對(duì)象不存在的問題。

那Optional存在的作用是啥?

其實(shí)Optional的作用僅僅是不用寫為空的判斷,這也是Optional這個(gè)類的作用作用,除了這個(gè),跟直接@Autowired對(duì)象并沒有其它區(qū)別。

注入Optional這種方式其實(shí)用的不多,在我的映像中,我在源碼中幾乎沒有看見這種注入方式。

7、ObjectFactory和ObjectProvider

ObjectFactory和ObjectProvider是Spring提供的兩接口

ObjectFactory

ObjectProvider繼承了ObjectFactory

ObjectProvider

@Autowired也可以直接注入這兩個(gè)接口。

@Autowired
private ObjectFactory messageNotifierObjectFactory;

@Autowired
private ObjectProvider messageNotifierObjectProvider;

代碼如下:

從這段代碼也可以看出,最終注入的其實(shí)是DependencyObjectProvider實(shí)現(xiàn)。

ObjectFactory也是用來做延遲注入的操作,跟@Lazy作用差不多,但是實(shí)現(xiàn)原理不一樣。

用上面的例子來說,注入ObjectFactory的時(shí)候并有創(chuàng)建MessageNotifier對(duì)象。

當(dāng)需要使用MessageNotifier的時(shí)候需要通過ObjectFactory的getObject方法獲取,此時(shí)才會(huì)真正創(chuàng)建MessageNotifier對(duì)象。

MessageNotifier messageNotifier = messageNotifierObjectFactory.getObject();

getObject實(shí)現(xiàn)如下

getObject

所以@Async注解導(dǎo)致的循環(huán)依賴異常不僅可以通過@Lazy注解解決,也可以通過注入ObjectFactory的方式解決。

同理,ObjectProvider也有延遲注入的功能,但是除了延遲注入之外,ObjectProvider額外提供了跟Optional安全注入的功能,這個(gè)功能ObjectFactory是沒有的。

上面的例子中,當(dāng)使用ObjectFactory的getObject方法時(shí),如果Spring容器中不存在MessageNotifier對(duì)象,此時(shí)也會(huì)拋NoSuchBeanDefinitionException異常。

但是ObjectProvider額外提供的getIfAvailable方法就支持獲取不存在的對(duì)象的功能,當(dāng)通過getIfAvailable獲取的對(duì)象不存在時(shí),只會(huì)返回null,并不會(huì)出拋異常。

getIfAvailable方法

對(duì)比一下與getObject方法的實(shí)現(xiàn),就是在獲取對(duì)象的時(shí)候是否要求對(duì)象獲取的對(duì)象不是必須的,這樣獲取不到就不會(huì)拋異常了。

ObjectFactory和ObjectProvider在框架內(nèi)部中使用的還是比較多的。

就比如說,在MybatisPlus自動(dòng)裝配的時(shí)候就大量使用ObjectProvider

并且泛型類型就是數(shù)組或者是集合,跟前面說的都對(duì)應(yīng)上了。

通過這種方式就可以安全的注入,當(dāng)Spring容器有這些對(duì)象的時(shí)候MybatisPlus就使用這些,沒有也不會(huì)報(bào)錯(cuò)。

8、JSR-330 Provider

首先,來講一下什么是JSR-330。

JSR是Java Specification Requests的縮寫,是一種Java標(biāo)準(zhǔn)規(guī)范。

而330算是一個(gè)版本,除了330,聽到的比較多的還有250。

這個(gè)規(guī)范定義了一些IOC的注解,我們熟知的比如@Resource、@PostConstruct、@PreDestroy注解都是JSR-250中提出的。

一些IOC的框架會(huì)基于這個(gè)標(biāo)準(zhǔn)來實(shí)現(xiàn)這些接口的功能,比如Spring、Dagger2等IOC框架都實(shí)現(xiàn)了這些注解的功能。

所以,如果你不使用Spring框架,使用其它的IOC框架,那么@Resource、@PostConstruct、@PreDestroy注解都是可以生效的。

在JSR-330中,提出了javax.inject.Provider這個(gè)接口

不過,想使用JSR-330這個(gè)接口,需要引入依賴


javax.inject
javax.inject
1

Spring也支持注入這個(gè)類型的接口

這個(gè)接口的功能跟前面提到的ObjectFactory功能是一樣的,也支持延遲注入的功能。

總結(jié)

到這Spring能夠注入的Bean的8種類型就講完了,其實(shí)這8種類型可以分為以下幾種功能:

  • 單一注入,就是注入一個(gè)單一的對(duì)象
  • 集合注入,可以注入數(shù)組或者集合
  • 延遲注入,比如@Lazy、ObjectFactory、ObjectProvider、JSR-330 Provider
  • 安全注入,不存在不會(huì)拋異常,比如Optional、ObjectProvider

這幾種方式并不是互斥的,比如說延遲注入也可以注入的是一個(gè)集合,前面舉的MyBaisPlus自動(dòng)裝配時(shí)ObjectProvider的使用就是很好的例子。

同時(shí)雖然本文舉例的是@Autowird注解和字段注入的方式,但上面提到的注入的Bean類型跟使用注解和注入方式?jīng)]什么關(guān)系,@Resource注解,構(gòu)造器注入,setter注入都是一樣的。


當(dāng)前名稱:一個(gè)你可能不曾注意的小東西,Spring依賴注入Bean類型的八種情況
本文來源:http://www.dlmjj.cn/article/cococep.html