Spring中的IOC深度解讀
spring容器
spring容器的概念,容器這個名字起的相當(dāng)好,容器可以放很多東西,我們的程序啟動的時候會創(chuàng)建spring容器,會給spring容器一個清單,清單中列出了需要創(chuàng)建的對象以及對象依賴關(guān)系,spring容器會創(chuàng)建和組裝好清單中的對象,然后將這些對象存放在spring容器中,當(dāng)程序中需要使用的時候,可以到容器中查找獲取,然后直接使用。
IOC:控制反轉(zhuǎn)
使用者之前使用B對象的時候都需要自己去創(chuàng)建和組裝,而現(xiàn)在這些創(chuàng)建和組裝都交給spring容器去給完成了,使用者只需要去spring容器中查找需要使用的對象就可以了;這個過程中B對象的創(chuàng)建和組裝過程被反轉(zhuǎn)了,之前是使用者自己主動去控制的,現(xiàn)在交給spring容器去創(chuàng)建和組裝了,對象的構(gòu)建過程被反轉(zhuǎn)了,所以叫做控制反轉(zhuǎn);IOC是是面相對象編程中的一種設(shè)計原則,主要是為了降低系統(tǒng)代碼的耦合度,讓系統(tǒng)利于維護(hù)和擴(kuò)展。
DI:依賴注入
依賴注入是spring容器中創(chuàng)建對象時給其設(shè)置依賴對象的方式,比如給spring一個清單,清單中列出了需要創(chuàng)建B對象以及其他的一些對象(可能包含了B類型中需要依賴對象),此時spring在創(chuàng)建B對象的時候,會看B對象需要依賴于哪些對象,然后去查找一下清單中有沒有包含這些被依賴的對象,如果有就去將其創(chuàng)建好,然后將其傳遞給B對象;可能B需要依賴于很多對象,B創(chuàng)建之前完全不需要知道其他對象是否存在或者其他對象在哪里以及被他們是如何創(chuàng)建,而spring容器會將B依賴對象主動創(chuàng)建好并將其注入到B中去,比如spring容器創(chuàng)建B的時候,發(fā)現(xiàn)B需要依賴于A,那么spring容器在清單中找到A的定義并將其創(chuàng)建好之后,注入到B對象中。
spring中依賴注入主要分為手動注入和自動注入:
手動注入需要由程序員自己配置、描述好依賴關(guān)系,來實現(xiàn)自動注入(但是實際開發(fā)中手動裝配的場景比較少,比如在缺少源碼的情況下可能會使用這種手動裝配情況)。
自動注入采用約定大于配置的方式來實現(xiàn)的,程序和spring容器之間約定好,遵守某一種都認(rèn)同的規(guī)則,來實現(xiàn)自動注入。
DI:依賴注入的實現(xiàn)方式
分別是基于構(gòu)造方法的依賴注入和基于setter(setXxxx(…))的依賴注入。
不管是手動裝配還是自動裝配都是基于這兩種方式或者變體方式來的;但是這里一定要回答到主要和變體兩個名詞,因為有的注入方式就不是這兩種,而是這兩種其中一種的變體方式;比如在一個類的屬性上面加@Autowired,這種方式注入屬性的方式就是利用了java的反射知識,field.set(value,targetObject);關(guān)于這個我在后面的文章中對spring源碼解析的時候會說明@Autowired的原理;所以@Autowired這種注入的方式是setter注入方式的一種變體

DI:依賴注入的自動裝配模型
依賴注入是一個過程,主要通過setter或構(gòu)造方法以及一些變體的方式完成把對象依賴、或者填充上的這個過程叫做依賴注入,不管手動裝配還是自動裝配都有這個過程;
手動裝配通過ref標(biāo)簽來指定依賴關(guān)系,而自動裝配沒有顯示的指定依賴關(guān)系,所以需要通過一些規(guī)則,來從容器中查找到符合條件的bean進(jìn)行自動裝配的工作,而自動裝配模型就是完成自動裝配依賴的手段體現(xiàn)。
每一種模型都使用了不同的技術(shù)去查找和填充bean;而從spring官網(wǎng)上面可以看到spring只提出了4中自動裝配模型(嚴(yán)格意義上是三種、因為第一種是no,表示不使用自動裝配、使用),這四個模型分別用一個整形來表示,存在spring的beanDefinition當(dāng)中,任何一個類默認(rèn)是no這個裝配模型

我們可以在AutowireCapableBeanFactory類中看下這幾種自動裝配模型對應(yīng)的整形分別是多少
public interface AutowireCapableBeanFactory extends BeanFactory {
int AUTOWIRE_NO = 0;
int AUTOWIRE_BY_NAME = 1;
int AUTOWIRE_BY_TYPE = 2;
int AUTOWIRE_CONSTRUCTOR = 3;
@Deprecated
int AUTOWIRE_AUTODETECT = 4;
}@Autowired就是根據(jù)byType來進(jìn)行自動裝配
我們先拋出@Autowired的查找邏輯的結(jié)論:
首先spring根據(jù)類型去容器中找,找到了直接注入。如果根據(jù)類型找到了多個,那么spring不會立馬異常,而是根據(jù)名字再去找,如果根據(jù)名字找到一個合理的則注入這個合理的。
如果沒有找到,再根據(jù)名字去找,找到了則注入,沒有找到則報異常。
我們再來用代碼來驗證下
定義一個空接口I,XY類分別實現(xiàn)I接口,Z類中注入I
public interface I {
}package com.yj.service.impl;
import org.springframework.stereotype.Component;
import com.yj.service.I;
@Component("ix")
public class X implements I{
}package com.yj.service.impl;
import org.springframework.stereotype.Component;
import com.yj.service.I;
@Component("iy")
public class Y implements I{
}@Component
public class Z {
@Autowired
private I ix;
public I getIx() {
return ix;
}
public void setIx(I ix) {
this.ix = ix;
}
}掃描配置類
package com.yj.conf;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.yj")
public class AppConfig {
}MyBeanFactoryProcessor
package com.yj.conf;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)beanFactory.getBeanDefinition("z");
//beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
System.out.println("beanDefinition.getAutowireMode():"+beanDefinition.getAutowireMode());
}
}首先,我們可以觀察到被@Autowired注解的z類的getAutowireMode值為0,不是2。而且我們?nèi)绻謩訉類的AutowireMode設(shè)置為ByType,只是根據(jù)類型來查找的話,會查出XY兩個bean,程序會報錯的。
但是采用@Autowired默認(rèn)的注入方式,是不會報錯的,也就是說@Autowired的查找邏輯并不能簡單的認(rèn)為等價于ByType,@Autowired首先根據(jù)類型然后再根據(jù)名字去查找,完成bean注入的過程。
到此這篇關(guān)于Spring中的IOC深度解讀的文章就介紹到這了,更多相關(guān)IOC深度解讀內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring mvc4中相關(guān)注解的詳細(xì)講解教程
這篇文章主要給大家介紹了關(guān)于spring mvc4中相關(guān)注解的相關(guān)資料,其中詳細(xì)介紹了關(guān)于@Controller、@RequestMapping、@RathVariable、@RequestParam及@RequestBody等等注解的相關(guān)內(nèi)容,需要的朋友可以參考借鑒,下面來一起看看吧。2017-06-06
java創(chuàng)建線程池的7種實現(xiàn)方法
在Java中線程池是一種管理線程的機(jī)制,它可以創(chuàng)建一組線程并重復(fù)使用它們,避免了創(chuàng)建和銷毀線程的開銷,這篇文章主要給大家介紹了關(guān)于java創(chuàng)建線程池的7種實現(xiàn)方法,需要的朋友可以參考下2023-10-10
Spring Boot 2.0快速構(gòu)建服務(wù)組件全步驟
這篇文章主要給大家介紹了關(guān)于Spring Boot 2.0快速構(gòu)建服務(wù)組件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring Boot 2.0具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
對比Java中的Comparable排序接口和Comparator比較器接口
Comparable和Comparator接口都可用作普通意義上對象間的比大小,但兩個接口在實例化方面的用法不盡相同,接下來我們就來詳細(xì)對比Java中的Comparable排序接口和Comparator比較器接口2016-05-05
java讀寫excel文件實現(xiàn)POI解析Excel的方法
在日常工作中,我們常常會進(jìn)行Excel文件讀寫操作,這篇文章主要介紹了java讀寫excel文件實現(xiàn)POI解析Excel的方法,實例分析了java讀寫excel的技巧,非常具有實用價值,需要的朋友可以參考下2018-10-10
Springboot使用redis實現(xiàn)接口Api限流的實例
本文介紹的內(nèi)容如題,就是利用redis實現(xiàn)接口的限流(某時間范圍內(nèi),最大的訪問次數(shù)),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07
Java httpcomponents發(fā)送get post請求代碼實例
這篇文章主要介紹了Java httpcomponents發(fā)送get post請求代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09
SpringBoot使用Editor.md構(gòu)建Markdown富文本編輯器示例
這篇文章主要介紹了SpringBoot使用Editor.md構(gòu)建Markdown富文本編輯器示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03

