国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Spring IoC是如何進行依賴注入的

開發 前端
DI(Dependency Injection),Spring IoC 不是一種技術,而是一種思想,通過這種思想,能夠指導我們設計出松耦合的程序代碼。

一、依賴注入(DI)

DI(Dependency Injection),Spring IoC 不是一種技術,而是一種思想,通過這種思想,能夠指導我們設計出松耦合的程序代碼。而Spring IoC這個思想的作用體現在兩個方面,一是如何將Bean裝配到容器中去以及如何從容器中獲取Bean,二是如何解決Bean之間的依賴關系,換句話說,就是如果由IoC容器來管理依賴關系,當一個Bean需要依賴另外一個Bean時,IoC容器如何實現這樣的依賴關系。

解決Spring中Bean之間的依賴的實現方式,在Spring的概念中就被稱之為依賴注入(Dependency Injection,DI)。普遍認為的Spring依賴注入的實現方式有三種:構造方法注入、setter方法注入、注解注入。但,就我而言,我認為應該劃分為兩種形式——基于XML注入和基于注解注入,然后再細分為下面的形式:

Spring IoC是如何進行依賴注入的

基于XML的注入方式是我們最先學習和使用的方式,也是最熟悉的方式,就簡單的做個介紹,舉個例子。

1. 通過構造方法注入

  1. public class UserServiceImpl implements UserService { 
  2.  
  3.     private UserDao userDao; 
  4.  
  5.     public UserServiceImpl(UserDao userDao) { 
  6.         this.userDao = userDao; 
  7.     } 
  8.  
  9.     /**繼承自UserService的方法**/ 

首先定義一個服務層UserServiceImpl,然后在其內部增加對dao層的引用userDao。

接下來就是添加一個構造方法public UserServiceImpl(UserDao userDao)以待Spring通過這個方法為userDao注入實例。

  1. <!--注冊userDao--> 
  2. <bean id="userDao" class="com.klasdq.sb.c1.di.dao.impl.UserDaoImpl"></bean> 
  3.  
  4. <!--注冊userService 并注入userDao--> 
  5. <bean id="userService" class="com.klasdq.sb.c1.di.service.impl.UserServiceImpl"> 
  6.         <constructor-arg name="userDao" ref="userDao"></constructor-arg> 
  7. </bean> 

最后在Spring XML配置文件中注入相應的bean實例。

通過構造方法的注入,必須要注入類中具有對應的構造方法,若沒有對應的構造方法,會出現報錯。

2. 通過setter方法注入

修改UserServiceImpl.java為:

  1. public class UserServiceImpl implements UserService { 
  2.  
  3.     private UserDao userDao; 
  4.  
  5.     public void setUserDao(UserDao userDao) { 
  6.         this.userDao = userDao; 
  7.     } 
  8.  
  9.     /**繼承自UserService的方法**/ 

再修改XML文件內容為:

  1. <!--注冊userDao--> 
  2. <bean id="userDao" class="com.klasdq.sb.c1.di.dao.impl.UserDaoImpl"></bean> 
  3.  
  4. <!--注冊userService 并注入userDao--> 
  5. <bean id="userService" class="com.klasdq.sb.c1.di.service.impl.UserServiceImpl"> 
  6.         <property name="userDao" ref="userDao"></property> 
  7. </bean> 

這兩種方式的區別在于,一、UserServiceImpl.java可以不用添加構造方法,但是必須存在一個無參構造方法(如public UserServiceImpl(),示例里面沒寫,是因為java默認會提供一個無參構造方法)以供Spring 容器注冊生成Bean(如userService)。二、XML文件中,采用構造方法注入時,需要使用這對標簽;而在setter方法注入時,使用 標簽。

在XML注入過程中,除了使用ref=""引用之外,還可以使用value=""設定具體的值,其效果和使用注解@Value差不多。

二、基于注解的依賴注入

三、Autowired

源碼:

  1. @Target({ElementType.CONSTRUCTOR, 
  2.          ElementType.METHOD, 
  3.          ElementType.PARAMETER, 
  4.          ElementType.FIELD, 
  5.          ElementType.ANNOTATION_TYPE}) 
  6. @Retention(RetentionPolicy.RUNTIME) 
  7. @Documented 
  8. public @interface Autowired { 
  9.     boolean required() default true; 

@Autowired是基于注解的依賴注入的關鍵點,它的源碼非常簡單,只有一個參數request(),這個參數的作用是標識注入Bean是否一定要注入,也就是說,在Spring容器沒有找到相應Bean時,如果其值為true,就會報出異常;如果其值為false,就不會出現異常,但在使用過程中,如果容器一直不對Bean進行注入,那么有可能出現空指針異常。

另外一點就是,源碼當中的@Target所包含的參數正好就是基于注解的依賴注入的注入方式種類,@Target決定了@Autowired能夠標注在哪些類型上面。

1. 通過構造方法注入:

  1. @Service("userService") 
  2. public class UserServiceImpl implements UserService { 
  3.  
  4.     private UserDao userDao; 
  5.  
  6.     @Autowired 
  7.     public UserServiceImpl(UserDao userDao) { 
  8.         this.userDao = userDao; 
  9.     } 
  10.     /**繼承自UserService的方法**/ 

根據開發文檔的說法,這種只有一個構造方法的情況,自Spring4.3以后,就不再需要添加@Autowired標注,也可以。但是,如果有多個構造方法時,是必須要對其中一個方法標注@Autowired,不然Spring會報出異常。

2. 通過setter方法注入

  1. @Service("userService") 
  2. public class UserServiceImpl implements UserService { 
  3.  
  4.     private UserDao userDao; 
  5.  
  6.     @Autowired 
  7.     public void setUserDao(UserDao userDao) { 
  8.         this.userDao = userDao; 
  9.     } 
  10.     /**繼承自UserService的方法**/ 

3. 通過字段注入

  1. @Service("userService") 
  2. public class UserServiceImpl implements UserService { 
  3.  
  4.     @Autowired 
  5.     private UserDao userDao; 
  6.  
  7.     /**繼承自UserService的方法**/ 

4. 通過方法入參注入

上面三種注入方式,都是比較熟悉的就不再多做闡述了。重點說一下參數注入,其實方法入參注入方式感覺上是和構造方法、setter方法注入形式差不多,相當于將構造方法、setter方法上的注解@Autowired放到入參的位置。說起來可能有些抽象,直接看例子:

  1. @Component 
  2. public class UserDaoImpl implements UserDao { 
  3.     //簡單返回一個User,模擬數據庫查找過程 
  4.     @Override 
  5.     public User getUser(Long id, String name){ 
  6.         User user = new User(); 
  7.         user.setId(id); 
  8.         user.setName(name); 
  9.         user.setAccount("12345678911"); 
  10.         user.setPassword("******"); 
  11.         user.setOtherInfo("this is a test account"); 
  12.         return user; 
  13.     } 
  1. //UserService類 
  2. @Service("userService") 
  3. public class UserServiceImpl implements UserService { 
  4.  
  5.     private UserDao userDao; 
  6.  
  7.    public UserServiceImpl(@Autowired UserDao userDao, 
  8.                           @Autowired User user) { 
  9.        System.out.println("UserServiceImpl: "+user); 
  10.        this.userDao = userDao; 
  11.    } 
  12.  
  13.     @Override 
  14.     public User getUser(Long id, String name){ 
  15.         return userDao.getUser(id,name); 
  16.     } 
  1. //簡單的配置類 
  2. //作用就是為標有@Componet(@Service也算)注解的類 生成Bean 
  3. //同時 為@Autowired標識下的Bean(對象) 注入實例 
  4. @Configuration 
  5. @ComponentScan 
  6. public class DIConfig { 
  7.  
  8.     //用于Service類中入參user的注入 
  9.     @Bean 
  10.     public User getUser(){ 
  11.         User u = new User(); 
  12.         u.setName("user inject into service"); 
  13.         return u; 
  14.     } 
  1. //測試類 
  2. //注意:使用JUnit4測試時,如果需要使用@Autowired注入那么必須添加 
  3. //@RunWith    標注使用Spring方式啟動(或者SpringBootRunner) 
  4. //@ContextConfiguration  掃描配置類 
  5. @RunWith(SpringRunner.class) 
  6. @ContextConfiguration(classes = DIConfig.class) 
  7. public class DITest { 
  8.  
  9.     //如果不添加測試類上兩個注解,會注入失敗 
  10.     @Autowired 
  11.     private UserService userService; 
  12.  
  13.     @Test 
  14.     public void testAutowired(){ System.out.println(userService.getUser(1L,"name")); 
  15.     } 

運行測試方法之后就得到以下結果:

public UserServiceImpl(@Autowired UserDao userDao,@Autowired User user)中的輸出結果:

Spring IoC是如何進行依賴注入的

public void testAutowired()測試方法中的輸出結果:

Spring IoC是如何進行依賴注入的

注意這里public UserServiceImpl(@Autowired UserDao userDao,@Autowired User user)的入參:

userDao是UserServiceImpl的字段,但user不是。也就是說,我們可以在構造方法中添加任意參數,只要是我們需要的,不一定要求該參數是類中屬性字段。

此外還有需要注意的是,這里所說的方法,不是任意的方法,而是構造方法或setter方法,這種public void initService(@Autowired UserDao userDao)自定義的方法是無法完成注入的。

四、@Primary 和 @Qualifier

在上面的例子中,我們注入使用到的bean,都只是容器中只有一個Bean實例的情況。那么當容器當中出現多個同類型的Bean時,如何處理呢?

修改配置類代碼如下:

  1. @Configuration 
  2. @ComponentScan 
  3. public class DIConfig { 
  4.  
  5.     @Bean 
  6.     public User getUser(){ 
  7.         User u = new User(); 
  8.         u.setName("this is user"); 
  9.         return u; 
  10.     } 
  11.  
  12.     @Bean 
  13.     public User getUser2(){ 
  14.         User u = new User(); 
  15.         u.setName("this is user2"); 
  16.         return u; 
  17.     } 

修改測試類:

  1. @RunWith(SpringRunner.class) 
  2. @ContextConfiguration(classes = DIConfig.class) 
  3. public class DITest { 
  4.  
  5.     @Autowired 
  6.     private User user; 
  7.  
  8.     @Test 
  9.     public void testAutowiredPriamry(){ 
  10.         System.out.println(user); 
  11.     } 

當不做其他處理時,結果為:

Spring IoC是如何進行依賴注入的

因為有兩個User Bean(getUser , getUser2 ,@Bean未注明的情況下,默認方法名為Bean Name)的存在,所以Spring無法確定使用那個進行注入。

修改方式:

  • 在@Bean中設置name,如@Bean(name="user"),當名字能夠匹配上private User user;時,也能完成注入。
  • 將private User user改寫成getUser或getUser2任意一個,也能完成注入。道理和上面一樣,Spring首先會按照type進行匹配,如果無法匹配,再按照名字匹配,都匹配不上時,自然拋出異常。

除此之外呢,Spring為我們提供了兩個注解來消除依賴注入時的歧義問題。

  • @Primary
    1. @Target({ElementType.TYPE,    // 類、接口、枚舉類型 
    2.          ElementType.METHOD})// 方法 
    3. @Retention(RetentionPolicy.RUNTIME) 
    4. @Documented 
    5. public @interface Primary { 

@Primary是一個設定相同類型Bean優先級的注解,也就是說,一旦在某個類型上添加@Priamry,當注入時,沒有明確指定Bean時,就會注入被@Priamry標識的Bean。

  1. @Configuration 
  2. @ComponentScan 
  3. public class DIConfig { 
  4.  
  5.     @Primary 
  6.     @Bean 
  7.     public User getUser(){ 
  8.         User u = new User(); 
  9.         u.setName("this is user"); 
  10.         return u; 
  11.     } 
  12.  
  13.     @Bean 
  14.     public User getUser2(){ 
  15.         User u = new User(); 
  16.         u.setName("this is user2"); 
  17.         return u; 
  18.     } 

比如上面這樣,在getUser()上添加相應注解,測試方法也能正常運行。

但是這種方法的問題就在于@Priamry可以用在很多類上,如果同一類型有多個Bean被標注了@Primary,那么@Priamry就失去了應有的效果。

  • @Qualifier

因此,Spring又提供了@Qualifier這個注解,直接標注在@Autowired注入的Bean上,為其明確指定注入某個Bean。

  1. @Target({ElementType.FIELD,  
  2.          ElementType.METHOD,  
  3.          ElementType.PARAMETER,  
  4.          ElementType.TYPE,  
  5.          ElementType.ANNOTATION_TYPE}) 
  6. @Retention(RetentionPolicy.RUNTIME) 
  7. @Inherited 
  8. @Documented 
  9. public @interface Qualifier { 
  10.     String value() default ""; 

@Qualifier可以出現任何@Autowired能夠出現的地方,與之配套使用。比如下面這樣:

  1. @RunWith(SpringRunner.class) 
  2. @ContextConfiguration(classes = DIConfig.class) 
  3. public class DITest {  
  4.  
  5.     //直接指定使用getUser2進行注入 
  6.     @Autowired 
  7.     @Qualifier("getUser2") 
  8.     private User user; 
  9.  
  10.     @Test 
  11.     public void testAutowiredPriamry(){ 
  12.         System.out.println(user); 
  13.     } 

這兩種注解都可以消除歧義,推薦使用@Bean(name="xxx")和@Qualifier(value="xxx")組合使用的方式`。但是如果開發環境中沒有歧義的存在,自然也就不需要使用這些了。

當然,上面只是對于@Autowired一些常用介紹,如果想要了解更多,可以查看Annotation-based Container Configuration。這個參考文檔當中有著更加詳細、豐富的介紹。

總結

總得來說,Spring是如何實現IoC的呢?首先,Spring提供了一個獲取和管理Bean的IoC容器。然后,再提供了一套依賴注入的機制去幫助IoC容器更好地管理各個Bean之間的依賴關系,從而更好地實現IoC的思想。一個Bean不可能完全脫離其他Bean的依賴關系而獨立存在,當一個Bean需要其他Bean的引入才能初始化時,就需要依賴注入這個機制。

舉例來說,假如存在一個A類想要去調用B接口的方法或者說需要B接口的一個實例。

傳統的程序流程是,使用一個C類實現B接口,然后A類創建一個C類的實例,從而調用其方法。

在Spring的依賴注入過程中就變成了,A類只需要在自己的內部添加一個注入接口(廣義上的接口,不是interface這個接口),這個接口可以是構造方法,也可以是setter方法或者說其他形式;同時添加一個對B接口的引用(private B b;)。

當真正需要生成A類的實例時,Spring IoC容器根據A類提供的接口,為其注入相應的Bean,而這個Bean可以是C類(class C implements B{}),也可以D類(class D implements B{})等等;具體是誰,根據Bean的裝配策略和IoC容器中的Bean來確定,不再由開發人員管理。

本文授權轉載自公眾號「良許Linux」。良許,世界500強外企Linux開發工程師,公眾號里分享大量Linux干貨,歡迎關注!

 

責任編輯:趙寧寧 來源: 今日頭條
相關推薦

2025-07-11 00:48:00

2013-04-15 17:55:12

Windows認證安全認證

2013-04-16 10:33:58

Windows 安全認微軟

2011-05-31 10:00:21

Android Spring 依賴注入

2024-05-08 08:16:11

2023-10-17 00:01:34

Linux操作系統

2010-08-02 16:33:11

Flex Spring

2021-05-06 07:58:57

Spring BeanIOCAOP

2021-01-22 06:35:44

IoCxml驅動技術

2022-04-30 08:50:11

控制反轉Spring依賴注入

2014-09-19 10:46:36

LuaCC++

2016-03-21 17:08:54

Java Spring注解區別

2020-12-29 08:34:08

spring循環依賴開發

2017-08-16 16:00:05

PHPcontainer依賴注入

2011-03-29 09:51:58

GuiceIOC

2020-04-06 14:50:43

MySQLSQL數據庫

2024-05-13 11:12:08

FO-DICOM開源應用開發

2021-03-15 10:23:44

IT支出技術投資CIO

2009-09-08 15:22:20

Spring依賴注入

2023-06-16 11:22:42

數據治理大數據
點贊
收藏

51CTO技術棧公眾號

91日韩视频| 国产精品三级a三级三级午夜 | 国产欧美日韩专区发布| 97中文在线| 亚洲色图综合久久| 暴力调教一区二区三区| 欧美一区一区| 欧美成人国产| 久久精品在这里| av成人国产| 亚州成人在线电影| 久久国产一区| 狂野欧美性猛交xxxxx视频| 国产成人中文字幕| 欧美野外猛男的大粗鳮| 亚洲国产成人在线| 狂野欧美激情性xxxx欧美| 免费久久久久久久久| 免费精品国产的网站免费观看| 99久久99久久精品免费看蜜桃 | heyzo在线欧美播放| 免费黄色网页在线观看| 亚洲成av人片在线观看无码| 在线观看成人免费| 91高清一区| 久久亚洲捆绑美女| 色爱区综合激月婷婷| 中文字幕中文字幕在线中一区高清| 四虎国产精品免费久久| 蜜桃av.网站在线观看| 69视频在线| 日韩一区二区免费看| 在线精品高清中文字幕| 欧美日韩精品一区二区三区| 97在线资源站| 久久精品黄色| 亚洲综合久久久| 一区二区三区免费看| 成年人网站国产| 污黄色在线观看| 中文字幕亚洲影视| 久久夜色撩人精品| 亚洲理论电影片| 自拍偷拍亚洲区| 日韩精品卡一| 日韩精品麻豆| 亚洲专区免费| 成年人网站国产| 欧美午夜丰满在线18影院| 91日韩视频在线观看| 国产精品美日韩| 国产一区二区三区丝袜 | 爱啪啪综合导航| 亚洲高清免费视频| rebdb初裸写真在线观看| 日本欧美国产在线| 国内自拍一区| 99se婷婷在线视频观看| av在线不卡观看免费观看| 中文字幕欧美一区二区| 国产黄色一区| 国产精品精品视频| 色老板亚洲精品一区| 精品国产一区二区三区久久久| 999www成人| 成人羞羞在线观看网站| 国产999精品| 成人网18免费网站| 亚洲一区二区三区加勒比| 久久精品人人做| 欧美激情精品久久久久久免费印度| 另类春色校园亚洲| 欧美精品七区| 亚洲影院免费观看| 色噜噜成人av在线| 蜜桃视频在线观看成人| 亚洲精品亚洲人成人网| 亚洲成人毛片| av一区二区三区在线| 亚洲成人www| 国产成人av一区| 成年午夜在线| 欧美视频裸体精品| 国产精品五月天| 久久九九久精品国产免费直播| 久久精品国产999大香线蕉| 日韩高清在线不卡| 国产精品直播网红| 欧美一区2区| 成人污污www网站免费丝瓜| 成av人片在线观看www| 在线观看视频污| 国产国产国产国产国产国产| 成人午夜视频在线观看免费| 成人av毛片| 天天干天天操天天做| 最近2019中文字幕第三页视频 | 99国精产品一二二线| 国产国语刺激对白av不卡| 国产免费成人av| 国产日韩欧美在线| 亚洲a级在线播放观看| 8v天堂国产在线一区二区| 狠狠操综合网| melody高清在线观看| 男人av在线| 日韩成人亚洲| 精品一区欧美| 午夜日韩福利| 成人av在线资源| 国产网站一区二区| 亚洲成av人片在www色猫咪| 精品久久人人做人人爽| 91九色视频在线| 日韩一区二区高清| 亚洲日本成人女熟在线观看| 久久精品国产精品| av免费精品一区二区三区| 奇米一区二区三区四区久久| 国产精品一二三在线| 日产精品一线二线三线芒果| 国产精品小说在线| 宅男在线精品国产免费观看| 福利在线国产| 97成人超碰| 久久一日本道色综合久久| 亚洲男帅同性gay1069| 欧美一二三四在线| 久久久久久久一区二区三区| av日韩免费电影| 1024欧美极品| 日本高清xxxx| 伊人网在线视频| 91亚洲无吗| 99精品国产热久久91蜜凸| 欧美丝袜一区二区| 91sa在线看| 波多野结衣50连登视频| 免费网站成人| 欧美国内亚洲| 亚洲成a人v欧美综合天堂下载 | 亚洲mv大片欧洲mv大片| 91亚洲精品久久久蜜桃| 国产成人精品亚洲日本在线桃色| 一区二区激情小说| 欧美精品激情在线观看| 91九色在线观看视频| 国精产品一区一区三区视频| 国产私人尤物无码不卡| 日韩综合在线| 亚洲一区二区三区美女| 欧美一级在线播放| 国产91在线视频观看| 操欧美女人视频| 成人综合在线网站| 一区二区在线视频观看| 欧美 亚洲 视频| 日韩欧美精品免费在线| 日韩av在线综合| 欧美高清性hdvideosex| 精品系列免费在线观看| 高清av一区二区| 国产精品无人区| 精品免费一区二区三区| 成人在线播放av| 精品久久一区二区三区蜜桃| 国产精品亚洲αv天堂无码| 成人片免费看| 国产欧美三级电影| 久久久www成人免费毛片麻豆| 国产视频精品久久久| 久久久久久久久久久久久久久久久久av| 五码日韩精品一区二区三区视频| 999精品在线观看| 无码人妻精品一区二区三区66| 国产精品蜜月aⅴ在线| xnxx国产精品| 69久久夜色精品国产7777 | 成人激情av网| 国产一区二区三区丝袜| 免费在线观看的毛片| 欧美三级情趣内衣| 日韩激情视频在线播放| 国产高潮免费视频| 国产日产高清欧美一区二区三区| 国产中文字幕精品| 一区二区三区国产| 国产成人福利网站| 污黄视频在线看| 韩国av一区二区| 91免费看国产| 九七久久人人| 亚洲国产视频直播| 国产伦视频一区二区三区| 川上优av中文字幕一区二区| 久久久久国产精品午夜一区| 亚洲成人激情综合网| 色哟哟免费网站| 亚洲精品女人| 五月天亚洲精品|