精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Spring依賴注入Bean類型的8種情況

jf_78858299 ? 來源:JAVA旭陽 ? 作者:JAVA旭陽 ? 2023-05-11 10:53 ? 次閱讀

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

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

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

1、普通對象

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

@Autowired
private UserService userService;

2、Collection及其子接口

除了支持注入一個單一的對象之外,@Autowired還支持注入一個Collection對象。

比如說,現在有個消息通知的接口MessageNotifier

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

@Autowired
private List<MessageNotifier> messageNotifiers;

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

圖片

3、數組

同理,@Autowired可實現了注入一個數組的功能。

@Autowired
private MessageNotifier[] messageNotifiers;

代碼如下:

圖片

4、Map

同樣的,@Autowired還可以注入一個Map。

@Autowired
private Map<String, MessageNotifier> messageNotifierMap;

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

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

圖片

5、@Lazy

當一個注入的字段加了@Lazy注解之后,那么此時就代表這個字段是延遲注入。

@Autowired
@Lazy
private MessageNotifier messageNotifier;

延遲注入并不是不注入,而是注入目標對象類型的代理對象,真正的目標是當需要用到的時候在創建。

圖片

如圖所示,當注入的MessageNotifier時加了@Lazy注解,那么此時注入的其實是MessageNotifier的代理對象,而真正的MessageNotifier對象并沒有創建,圖中代理對象我稱為MessageNotifierProxy

由于注入的是對象是代理對象MessageNotifierProxy,那么真正被使用的就是MessageNotifierProxy,一旦調用了MessageNotifierProxy的方法,此時MessageNotifierProxy會去Spring容器中查找真正的MessageNotifier對象,然后再調用MessageNotifier對象的方法。

代碼如下:

圖片

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

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

6、Optional

Optional是JDK1.8提供的一個api,可以優雅的解決判空的問題。

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

@Autowired
private Optional<MessageNotifier> messageNotifier;

代碼如下:

圖片

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

比如說,MessageNotifier這個對象Spring容器中并沒有,如果直接注入,此時會拋NoSuchBeanDefinitionException異常

圖片

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

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

那Optional存在的作用是啥?

其實Optional的作用僅僅是不用寫為空的判斷,這也是Optional這個類的作用作用,除了這個,跟直接@Autowired對象并沒有其它區別。

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

7、ObjectFactory和ObjectProvider

ObjectFactory和ObjectProvider是Spring提供的兩接口

圖片

ObjectFactory

ObjectProvider繼承了ObjectFactory

圖片

ObjectProvider

@Autowired也可以直接注入這兩個接口。

@Autowired
private ObjectFactory<MessageNotifier> messageNotifierObjectFactory;

@Autowired
private ObjectProvider<MessageNotifier> messageNotifierObjectProvider;

代碼如下:

圖片

從這段代碼也可以看出,最終注入的其實是DependencyObjectProvider實現。

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

用上面的例子來說,注入ObjectFactory的時候并有創建MessageNotifier對象。

當需要使用MessageNotifier的時候需要通過ObjectFactory的getObject方法獲取,此時才會真正創建MessageNotifier對象。

MessageNotifier messageNotifier = messageNotifierObjectFactory.getObject();

getObject實現如下

圖片

getObject

所以@Async注解導致的循環依賴異常不僅可以通過@Lazy注解解決,也可以通過注入ObjectFactory的方式解決。

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

上面的例子中,當使用ObjectFactory的getObject方法時,如果Spring容器中不存在MessageNotifier對象,此時也會拋NoSuchBeanDefinitionException異常。

但是ObjectProvider額外提供的getIfAvailable方法就支持獲取不存在的對象的功能,當通過getIfAvailable獲取的對象不存在時,只會返回null,并不會出拋異常。

圖片

getIfAvailable方法

對比一下與getObject方法的實現,就是在獲取對象的時候是否要求對象獲取的對象不是必須的,這樣獲取不到就不會拋異常了。

ObjectFactory和ObjectProvider在框架內部中使用的還是比較多的。

就比如說,在MybatisPlus自動裝配的時候就大量使用ObjectProvider

圖片

并且泛型類型就是數組或者是集合,跟前面說的都對應上了。

通過這種方式就可以安全的注入,當Spring容器有這些對象的時候MybatisPlus就使用這些,沒有也不會報錯。

8、JSR-330 Provider

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

JSR是Java Specification Requests的縮寫,是一種Java標準規范。

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

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

一些IOC的框架會基于這個標準來實現這些接口的功能,比如Spring、Dagger2等IOC框架都實現了這些注解的功能。

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

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

圖片

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

<dependency>
    <groupId>javax.inject<span class="hljs-name"groupId>
    <artifactId>javax.inject<span class="hljs-name"artifactId>
    <version>1<span class="hljs-name"version>
<span class="hljs-name"dependency>

Spring也支持注入這個類型的接口

圖片

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

總結

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

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

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

同時雖然本文舉例的是@Autowird注解和字段注入的方式,但上面提到的注入的Bean類型跟使用注解和注入方式沒什么關系,@Resource注解,構造器注入,setter注入都是一樣的。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    8498

    瀏覽量

    150837
  • 源碼
    +關注

    關注

    8

    文章

    633

    瀏覽量

    29140
  • spring
    +關注

    關注

    0

    文章

    338

    瀏覽量

    14311
收藏 人收藏

    評論

    相關推薦

    java spring教程

    Spring核心概念介紹控制反轉(IOC)依賴注入(DI)集合對象注入Bean的管理BeanFactoryApplicationConte
    發表于 09-11 11:09

    什么是java spring

    。在SSH項目中管理事務以及對象的注入Spring是非侵入式的:基于Spring開發的系統中的對象一般不依賴Spring的類。組成
    發表于 09-11 11:16

    spring實例

    ;UTF-8"?><!DOCTYPE beans PUBLIC"-//SPRING//DTD BEAN//EN""http://www.springframework.org
    發表于 09-11 11:22

    怎么閱讀Spring源碼

    注入)。如果其中有一個類container里沒找到,則拋出異常,比如常見的spring無法找到該類定義,無法wire的異常。還有就是嵌套bean則用了一下遞歸,container會放到
    發表于 05-04 15:21

    三大框架之Spring

    ;出現了Spring,可以自動創建需要被調用的對象以及進行屬性注入,也可以維護這些bean(具體的java類)之間的關系;
    發表于 05-27 07:21

    Spring工作原理

    依賴關系核心:bean工廠;在Spring中,bean工廠創建的各個實例稱作bean二.AOP(Aspect-Oriented Progr
    發表于 07-10 07:41

    spring教程ppt

    主要內容Spring 概述Spring 整體結構Spring實例Spring核心概念介紹控制反轉(IOC)依賴
    發表于 09-11 11:00 ?138次下載
    <b class='flag-5'>spring</b>教程ppt

    解析加載及實例化Bean的順序(零配置)

    作者丨低調的JVM 來自丨CSDN https://blog.csdn.net/qq_27529917/article/details/79329809 在使用Spring時,Bean之間會有些依賴
    的頭像 發表于 08-04 16:08 ?1300次閱讀

    Spring開發過程中依賴注入的幾個知識點

    轉自丨https://juejin.cn/post/6844904056230690824 本章的內容主要是想探討我們在進行 Spring 開發過程當中,關于依賴注入的幾個知識點。感興趣的讀者可以
    的頭像 發表于 08-27 09:18 ?1628次閱讀

    bean放入Spring容器中有哪些方式

    bean放入Spring容器中有哪些方式?
    的頭像 發表于 09-19 15:25 ?693次閱讀

    從源碼層面深度剖析Spring循環依賴

    參考圖中 spring 解決循環依賴 的過程可知,spring 利用三級緩中的 objectFactory 生成并返回一個 early 對象,提前暴露這個 early 地址,供其他對象依賴
    的頭像 發表于 12-22 10:34 ?515次閱讀

    Spring Dependency Inject與Bean Scops注解

    DependsOn`注解可以配置Spring IoC容器在初始化一個Bean之前,先初始化其他的Bean對象。下面是此注解使用示例代碼:
    的頭像 發表于 04-07 11:35 ?662次閱讀
    <b class='flag-5'>Spring</b> Dependency Inject與<b class='flag-5'>Bean</b> Scops注解

    Spring容器原始Bean是如何創建的?Spring源碼中方法的執行順序

    這個話題其實非常龐大,我本來想從 getBean 方法講起,但一想這樣講完估計很多小伙伴就懵了,所以我們還是一步一步來,今天我主要是想和小伙伴們講講 Spring 容器創建 Bean 最最核心的 createBeanInstance 方法,這個方法專門用來創建一個原始
    的頭像 發表于 08-04 10:12 ?576次閱讀
    <b class='flag-5'>Spring</b>容器原始<b class='flag-5'>Bean</b>是如何創建的?<b class='flag-5'>Spring</b>源碼中方法的執行順序

    Spring依賴注入的方式

    Spring 是一個開源的輕量級框架,可以用于構建企業級應用程序。其最重要的特性之一是依賴注入(Dependency Injection,DI),這是一設計模式,它可以幫助我們解耦代
    的頭像 發表于 11-22 15:12 ?462次閱讀

    Spring依賴注入的四方式

    Spring框架中,依賴注入是一核心的概念和機制。通過依賴注入,我們可以讓對象之間的
    的頭像 發表于 12-03 15:11 ?1900次閱讀