日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
長(zhǎng)文干貨丨一文搞懂IoC的依賴(lài)注入

 一、注解驅(qū)動(dòng)IoC

企業(yè)建站必須是能夠以充分展現(xiàn)企業(yè)形象為主要目的,是企業(yè)文化與產(chǎn)品對(duì)外擴(kuò)展宣傳的重要窗口,一個(gè)合格的網(wǎng)站不僅僅能為公司帶來(lái)巨大的互聯(lián)網(wǎng)上的收集和信息發(fā)布平臺(tái),創(chuàng)新互聯(lián)公司面向各種領(lǐng)域:柴油發(fā)電機(jī)成都網(wǎng)站設(shè)計(jì)全網(wǎng)整合營(yíng)銷(xiāo)推廣解決方案、網(wǎng)站設(shè)計(jì)等建站排名服務(wù)。


xml驅(qū)動(dòng)的IoC容器使用的是ClassPathXmlApplicationContext讀取xml內(nèi)bean信息

注解驅(qū)動(dòng)的IoC容器使用的是AnnotationConfigApplicationContext讀取Java類(lèi)中的bean信息

1. AnnotationConfigApplicationContext 的注冊(cè)使用

相比于xml文件作為驅(qū)動(dòng), 注解驅(qū)動(dòng)需要指明配置類(lèi) 一個(gè)配置類(lèi)可以理解為"相當(dāng)于"一個(gè)xml 配置類(lèi)只需要在類(lèi)上標(biāo)注注解 @Configuration

 
 
 
 
  1. @Configuration 
  2. public class DemoConfiguration { 

在xml中聲明bean的方式

在配置類(lèi)中使用的是@Bean注解

 
 
 
 
  1.  

說(shuō)明: 向IoC容器注冊(cè)一個(gè)類(lèi)型為Persion,id為Person的Bean

方法名表示的是bean的id 返回值表示的是注冊(cè)的bean的類(lèi)型

@Bean注解也可以顯示的聲明bean的id 如 @Bean("person1")

 
 
 
 
  1. @Bean 
  2. public Person person() { 
  3.     return new Person(); 

2. 注解IoC容器的初始化

 
 
 
 
  1. public class AnnotationConfigApplication { 
  2.     public static void main(String[] args) { 
  3.         ApplicationContext ctx = new AnnotationConfigApplicationContext(DemoConfiguration.class); 
  4.         Person person = ctx.getBean(Person.class); 
  5.         System.out.println(person); 
  6.     } 

運(yùn)行后Person控制臺(tái)打印結(jié)果

 
 
 
 
  1. com.huodd.bean.Person@55536d9e 

3. 組件的注冊(cè)和掃描

上述初始化時(shí) 我們?cè)谑褂肁nnotationConfigApplicationContext時(shí)傳遞了參數(shù) Class ... componentClasses

翻看AnnotationConfigApplicationContext的構(gòu)造方法可以發(fā)現(xiàn)還可以傳遞參數(shù)的參數(shù)類(lèi)型還有 String... basePackages

這里就涉及到組件的注冊(cè)和掃描

  • 這里可以思考一個(gè)問(wèn)題, 如果我們要注冊(cè)的組件特別多, 那進(jìn)行編寫(xiě)這些@Bean的時(shí)候代碼工作量也會(huì)特別多,這時(shí)候該如何解決呢?

Spring 給我們提供了幾個(gè)注解,可以幫助我們快速注冊(cè)需要的組件, 這些注解被稱(chēng)為模式注解(stereotype annotations)

@Component

@Component可以說(shuō)是所有組件注冊(cè)的根源 在類(lèi)上標(biāo)注 @Component 代表該類(lèi)被注冊(cè)到IoC容器中作為一個(gè)Bean

 
 
 
 
  1. @Component 
  2. public class Person { 

如果未指定 Bean 的名稱(chēng) 默認(rèn)規(guī)則是 "類(lèi)名稱(chēng)首字母小寫(xiě)" 上面的bean名稱(chēng)默認(rèn)會(huì)是 person

如果要自定義bean的名稱(chēng) 可以在@Component聲明value的值即可 如

 
 
 
 
  1. @Component("person1") 
  2. public class Person { 

在xml中相當(dāng)于

 
 
 
 
  1.  

@ComponentScan

這個(gè)時(shí)候 如果我們直接運(yùn)行啟動(dòng)類(lèi) 獲取Person的bean對(duì)象,會(huì)報(bào)錯(cuò)NoSuchBeanDefinitionException 這是為什么呢?

因?yàn)槲覀冎皇锹暶髁私M件,而后直接啟動(dòng)了IoC容器,這樣容器是感知不到有@Component存在的,

解決方案1:

我們需要在寫(xiě)配置類(lèi)時(shí)再額外標(biāo)注一個(gè)新的注解@ComponentScan

目的是告訴IoC容器 我要掃描哪個(gè)包下面的帶有@Component注解的類(lèi)

 
 
 
 
  1. @Configuration 
  2. @ComponentScan("com.huodd.bean") 
  3. public class DemoComponentScanConfiguration { 

: 如果不指定掃描路徑, 則默認(rèn)掃描本類(lèi)所在包及所有子包下帶有@Component的組件

啟動(dòng)類(lèi)代碼如下:

 
 
 
 
  1. public class AnnotationConfigApplication { 
  2.     public static void main(String[] args) { 
  3.         ApplicationContext ctx = new AnnotationConfigApplicationContext(DemoComponentScanConfiguration.class); 
  4.         Person person = ctx.getBean(Person.class); 
  5.         System.out.println(person); 
  6.     } 

解決方案2:

這里也可以不寫(xiě)@ComponentScan 而直接在AnnotationConfigApplicationContext方法參數(shù)內(nèi)傳入String類(lèi)型的包掃描路徑 代碼如下

 
 
 
 
  1. public class AnnotationConfigApplication { 
  2.     public static void main(String[] args) { 
  3.         ApplicationContext ctx = new AnnotationConfigApplicationContext("com.huodd.bean"); 
  4.         Person person = ctx.getBean(Person.class); 
  5.         System.out.println(person); 
  6.     } 

PS: 組件掃描并非是注解驅(qū)動(dòng)IoC所特有的, 其實(shí)在xml驅(qū)動(dòng)的IoC模式下 同樣可以啟用組件掃描, 只需要在xml中聲明一個(gè)標(biāo)簽即可

 
 
 
 
  1.  

這里需要注意下: 如需要掃描多個(gè)路徑,需要寫(xiě)多個(gè)標(biāo)簽 也就是 一個(gè)標(biāo)簽只能聲明一個(gè)根包

組件注冊(cè)的補(bǔ)充

SpringFramework 提供了在進(jìn)行Web開(kāi)發(fā)三層架構(gòu)時(shí)的擴(kuò)展注解: 分別為 @Controller、 @Service 、@Repository 小伙伴有沒(méi)有很熟悉?

分別代表 表現(xiàn)層、業(yè)務(wù)層、持久層 這三個(gè)注解的作用與 @Component完全一樣 扒開(kāi)源碼我們可以看到 底層在這三個(gè)注解類(lèi)上又添加了 @Component

 
 
 
 
  1. @Target({ElementType.TYPE}) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. @Documented 
  4. @Component 
  5. public @interface Service { 

這樣 我們?cè)谶M(jìn)行符合三層架構(gòu)的開(kāi)發(fā)時(shí) 對(duì)于相應(yīng)的如 ServiceImpl等 就可以直接標(biāo)注 @Service 等注解了

@Configuration

@Configuration 底層也有標(biāo)注@Component

 
 
 
 
  1. @Target({ElementType.TYPE}) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. @Documented 
  4. @Component 
  5. public @interface Configuration { ... } 

由此可以說(shuō)明,配置類(lèi)不是向我們所想的那樣,只是單純的做一個(gè)配置而已, 它也會(huì)被視為 bean,也被注冊(cè)到IoC容器里面

4. 注解驅(qū)動(dòng)與xml驅(qū)動(dòng)互相引用

4.1 xml引用注解

需開(kāi)啟注解配置 再注冊(cè)相應(yīng)配置類(lèi)

 
 
 
 
  1.  
  2.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  3.        xmlns:context="http://www.springframework.org/schema/context" 
  4.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  5.         https://www.springframework.org/schema/beans/spring-beans.xsd  
  6.         http://www.springframework.org/schema/context  
  7.         https://www.springframework.org/schema/context/spring-context.xsd"> 
  8.  
  9.      
  10.      
  11.      
  12.      
  13.  

4.2 注解引用XMl

 
 
 
 
  1. @Configuration 
  2. @ImportResource("classpath:annotation/demo-beans.xml") 
  3. public class ImportXmlAnnotationConfiguration {  

 二、IoC的依賴(lài)注入

1.Setter屬性注入

創(chuàng)建對(duì)象 將屬性值set進(jìn)去 之后返回對(duì)象

 
 
 
 
  1. @Bean 
  2. public Person person() { 
  3.     Person person = new Person(); 
  4.     person.setId(1); 
  5.     person.setName("PoXing"); 
  6.     person.setAge(18); 
  7.     return person; 

xml中的setter注入

 
 
 
 
  1.  
  2.      
  3.      
  4.      
  5.  

2. 構(gòu)造器注入

使用構(gòu)造器注入,需要在bean本身添加有參構(gòu)造方法, 如在Person中添加有參構(gòu)造方法如下

 
 
 
 
  1. public Person(Integer id, String name, Integer age) { 
  2.         this.id = id; 
  3.         this.name = name; 
  4.         this.age = age; 

注解驅(qū)動(dòng)中,我們創(chuàng)建bean的時(shí)候注入屬性時(shí) 就需要同時(shí)指定參數(shù)值

 
 
 
 
  1. @Bean 
  2. public Person person() { 
  3.     return new Person(1, "PoXing", 18); 

xml驅(qū)動(dòng)中如下

 
 
 
 
  1.  
  2.      
  3.      
  4.      
  5.      
  6.  

3. 注解式屬性注入

這里先說(shuō)明一下,為何會(huì)有注解式屬性值注入. 細(xì)心的小伙伴可能會(huì)發(fā)現(xiàn) 上面我們談到的 Setter屬性注入、構(gòu)造器注入 好像在只能是在使用 @Bean注解的時(shí)候時(shí)候使用, 但是 如果是通過(guò)標(biāo)注 @Component注解的組件呢(像前面我們的Person類(lèi)中標(biāo)注了@Component注解),怎么給它設(shè)定屬性值, 該節(jié)主要就是說(shuō)一下這部分

@Component 下的屬性注入

這里我們使用Dog類(lèi)做為演示(這里我悄悄的添加了@Component注解 自己嘗試的小伙伴要注意哦 否則會(huì)報(bào)錯(cuò)的)

 
 
 
 
  1. @Component 
  2. public class Dog { 
  3.     private Integer id; 
  4.     private String name; 
  5.     private Integer age; 
  6.  
  7.    ... 省略 Getter、Setter 
  8.    ... 省略 toString 
  9.  

這里要實(shí)現(xiàn)注解式屬性注入,可以直接在要注入的字段上標(biāo)注 @Value注解 如

 
 
 
 
  1. @Value("1") 
  2. private Integer id; 
  3.  
  4. @Value("wangcai") 
  5. private String name; 
  6.  
  7. @Value("3") 
  8. private Integer age; 

啟動(dòng)類(lèi)代碼如下

 
 
 
 
  1. public class DiApplication { 
  2.     public static void main(String[] args) { 
  3.         ApplicationContext ctx = new AnnotationConfigApplicationContext("com.huodd.bean"); 
  4.         Dog dog = ctx.getBean(Dog.class); 
  5.         System.out.println(dog); 
  6.     } 

控制臺(tái)打印結(jié)果

 
 
 
 
  1. Dog{id=1, name='wangcai', age=3} 

外部配置文件(@PropertySource)

這里主要是解決上面的@Value中注入 我們把屬性值直接固定寫(xiě)死了,如果要修改 還要去Java代碼中去修改,很不符合開(kāi)發(fā)規(guī)范,

SpringFramework為我們擴(kuò)展了新的注解@PropertySource 主要用來(lái)導(dǎo)入外部配置文件

1.這里我們創(chuàng)建一個(gè) dog.properties

 
 
 
 
  1. dog.id=1 
  2. dog.name=wangcai 
  3. dog.age=3 

2.引入配置文件

 
 
 
 
  1. @PropertySource("classpath:di/dog.properties") 
  2. @ComponentScan("com.huodd.bean") 
  3. @Configuration 
  4. public class DemoComponentScanConfiguration { 

3.Dog類(lèi)中屬性注入 這里@Value需要配合占位符 來(lái)獲取properties配置文件中的內(nèi)容

 
 
 
 
  1. @Value("${dog.id}") 
  2. private Integer id; 
  3.  
  4. @Value("${dog.name}") 
  5. private String name; 
  6.  
  7. @Value("${dog.age}") 
  8. private Integer age; 

4.修改一下啟動(dòng)類(lèi)

 
 
 
 
  1. public class DiApplication { 
  2.     public static void main(String[] args) { 
  3.         ApplicationContext ctx = new AnnotationConfigApplicationContext(DemoComponentScanConfiguration.class); 
  4.         Dog dog = ctx.getBean(Dog.class); 
  5.         System.out.println(dog); 
  6.     } 

控制臺(tái)打印結(jié)果如下

 
 
 
 
  1. Dog{id=1, name='wangcai', age=3} 

此時(shí)配置文件的屬性已經(jīng)注入成功

4.自動(dòng)注入

在xml模式中有ref屬性 可以將一個(gè)bean注入到另外一個(gè)bean中, 注解模式中也同樣可以

@Autowired

給Dog的bean中注入 Person的Bean (即 給dog指定它的主人)

方法1 → 在屬性上標(biāo)注

 
 
 
 
  1. @Component 
  2. public class Dog { 
  3.     // ...... 
  4.     @Autowired 
  5.     private Person person; 

方法2 → 使用構(gòu)造器注入方式

 
 
 
 
  1. @Component 
  2. public class Dog { 
  3.     // ...... 
  4.     private Person person; 
  5.  
  6.     @Autowired 
  7.     public Dog(Person person) { 
  8.      this.person = person; 
  9.     } 

方法3 → 使用setter方法注入

 
 
 
 
  1. @Component 
  2. public class Dog { 
  3.     // ...... 
  4.     private Person person; 
  5.      
  6.     @Autowired 
  7.     public void setPerson(Person person) { 
  8.         this.person = person; 
  9.     } 

JSR250規(guī)范下的@Resource

@Resource也是用來(lái)屬性注入的注解

它與@Autowired的區(qū)別是:

  • @Autowired是按照類(lèi)型注入
  • @Resource是按照屬性名(也就是bean的名稱(chēng))注入

@Resource 注解相當(dāng)于標(biāo)注 @Autowired @Qualifier

@Qualifier這里簡(jiǎn)要說(shuō)明下,為指定bean的名稱(chēng)而存在,如果存在多個(gè)相同的bean,而bean的名稱(chēng)不同,我們可以使用@Autowired 配置 @Qualifier注解

如: 下面表示該Dog類(lèi)注入的主人Bean是名稱(chēng)為 xiaowang的, 而當(dāng)前容器內(nèi)可能存在多個(gè) 主人bean對(duì)象 比如 xiaoli、xiaoming ....

 
 
 
 
  1. @Component 
  2. public class Dog { 
  3.     // ...... 
  4.     @Autowired 
  5.     @Qualifier("xiaowang") 
  6.     private Person person; 

下面如果使用@Resource 可以更方便些 代碼如下

 
 
 
 
  1. @Component 
  2. public class Dog { 
  3.     // ...... 
  4.     @Resource(name="xiaowang") 
  5.     private Person person; 

JSR330規(guī)范下的@Inject

@Inject注解也是按照類(lèi)型注入,與@Autowire的策略一樣, 不過(guò)如要使用@Inject 需要額外的導(dǎo)入依賴(lài)

 
 
 
 
  1.  
  2.  
  3.     javax.inject 
  4.     javax.inject 
  5.     1 
  6.  

后面的使用方法就與SpringFramework 原生的 @Autowire + @Qualifier 相同了

 
 
 
 
  1. @Component 
  2. public class Dog { 
  3.      
  4.     @Inject // 等同于@Autowired 
  5.     @Named("xiaowang") // 等同于@Qualifier 
  6.     private Person person; 

它與@Autowired的區(qū)別是:

  • @Autowired所在的包為 org.springframework.beans.factory.annotation.Autowired 即為 SpringFramework 提供的
  • @Inject所在的包為 javax.inject.Inject 屬于JSR的規(guī)范 也就是說(shuō)如果不使用SpringFramework時(shí)可以使用該注解

5. 復(fù)雜類(lèi)型注入

Array注入

 
 
 
 
  1.  
  2.      
  3.         PoXing 
  4.         LaoWang 
  5.      
  6.  

List注入

 
 
 
 
  1.  
  2.      
  3.         13000000000 
  4.         13000000001 
  5.      
  6.  

Set注入-

 
 
 
 
  1.  
  2.  
  3. --- 
  4.  
  5.  
  6.      
  7.          
  8.          
  9.      
  10.  

Map注入

 
 
 
 
  1.  
  2.      
  3.          
  4.           
  5.          
  6.          
  7.               
  8.          
  9.      
  10.  

Properties注入

 
 
 
 
  1.  
  2.      
  3.         男 
  4.         18 
  5.      
  6.  

面試題

1.@Autowired注入原理是什么?

  1. 先拿屬性對(duì)應(yīng)的類(lèi)型,去IoC容器中找相應(yīng)的Bean
  2. 如果沒(méi)有找到 直接拋出NoUniqueBeanDefinitionException異常
  3. 如果找到一個(gè) 直接返回
  4. 如果找到多個(gè)相同類(lèi)型的bean 再拿屬性名去與這多個(gè)bean的id進(jìn)行對(duì)比
  5. 如果有多個(gè)或者沒(méi)有 則會(huì)拋出NoUniqueBeanDefinitionException異常
  6. 如果只有一個(gè) 直接返回

2.依賴(lài)注入的方式有哪些,都有什么區(qū)別

3.自動(dòng)注入的注解對(duì)比

@Qualifier :如果被標(biāo)注的成員/方法在根據(jù)類(lèi)型注入時(shí)發(fā)現(xiàn)有多個(gè)相同類(lèi)型的 Bean ,則會(huì)根據(jù)該注解聲明的 name 尋找特定的 bean

@Primary :如果有多個(gè)相同類(lèi)型的 Bean 同時(shí)注冊(cè)到 IOC 容器中,使用 “根據(jù)類(lèi)型注入” 的注解時(shí)會(huì)注入標(biāo)注 @Primary 注解的 bean 即默認(rèn)策略

4.使用依賴(lài)注入有什么優(yōu)缺點(diǎn)

依賴(lài)注入作為 IOC 的實(shí)現(xiàn)方式之一,目的就是解耦,我們不需要直接去 new 那些依賴(lài)的類(lèi)對(duì)象就可以直接從容器中去取來(lái)使用, 如果組件存在多級(jí)依賴(lài),依賴(lài)注入可以將這些依賴(lài)的關(guān)系簡(jiǎn)化。

依賴(lài)對(duì)象的可配置:通過(guò) xml 或者注解聲明,可以指定和調(diào)整組件注入的對(duì)象,借助 Java 的多態(tài)特性,可以不需要大批量的修改就完成依賴(lài)注入的對(duì)象替換


網(wǎng)頁(yè)標(biāo)題:長(zhǎng)文干貨丨一文搞懂IoC的依賴(lài)注入
本文地址:http://www.5511xx.com/article/dpgjopd.html