溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

什么是IOC容器設計理念以及源碼怎么寫

發布時間:2021-10-20 10:41:18 來源:億速云 閱讀:152 作者:柒染 欄目:大數據

什么是IOC容器設計理念以及源碼怎么寫,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

?、IOC核?理論回顧
知識點:
1. Ioc理念概要
2. 實體Bean的創建
3. Bean的基本特性
4. 依賴注?
1、Ioc理論概要
在JAVA的世界中,?個對象A怎么才能調?對象B?通常有以下?種?法。
類別描述時間點
外部傳?
構造?法傳?創建引?對象時
屬性設置傳?設置對象狀態時
運?時做為參數傳?調?時
內部創建
屬性中直接創建創建引?對象時
初始化?法創建創建引?對象時
運?時動態創建調?時
上表可以看到, 引??個對象可以在不同地點(其它引?者)、不同時間由不同的?法完
成。如果B只是?個?常簡單的對象 如直接new B(),怎樣都不會覺得復雜,?如你從來不會
覺得創建?個St ring 是?個件復雜的事情。但如果B 是?個有著復雜依賴的Service對象,這
時在不同時機引?B將會變得很復雜。
?時?刻都要維護B的復雜依賴關系,試想B對象如果項?中有上百過,系統復雜度將會成陪
數增加。
IOC容器的出現正是為解決這?問題,其可以將對象的構建?式統?,并且?動維護對象的依
賴關系,從?降低系統的實現成本。前提是需要提前對?標對象基于XML進?聲明。
2、實體Bean的構建
a. 基于Class構建
b. 構造?法構建
c. 靜態???法創建
d. Fact oryBean創建
1、基于ClassName構建
這是最常規的?法,其原理是在spring底層會基于class 屬性 通過反射進?構建。
2、構造?法構建
如果需要基于參數進?構建,就采?構造?法構建,其對應屬性如下:
name:構造?法參數變量名稱
t ype:參數類型
index:參數索引,從0開始
value:參數值,spring 會?動轉換成參數實際類型值
ref :引?容串的其它對象
3、靜態???法創建
<bean class="com.tuling.spring.1 HelloSpring"></bean>
1 <bean class="com.tuling.spring.HelloSpring">
2 <constructor-arg name="name" type="java.lang.String" value="luban"/>
3 <constructor-arg index="1" type="java.lang.String" value="sex" />
4 </bean>
1 <bean class="com.tuling.spring.HelloSpring" factory-method="build">
2 <constructor-arg name="type" type="java.lang.String" value="B"/>
3 </bean>
如果你正在對?個對象進?A/B測試 ,就可以采?靜態???法的?式創建,其于策略
創建不同的對像或填充不同的屬性。
該模式下必須創建?個靜態???法,并且?法返回該實例,spring 會調?該靜態?法
創建對象。
4、Fact oryBean創建
指定?個Bean??來創建對象,對象構建初始化 完全交給該??來實現。配置Bean時指定該
??類的類名。
3、bean的基本特性
???? 作?范圍
???? ?命周期
???? 裝載機制
public static HelloSpring build(1 String type) {
2 if (type.equals("A")) {
3 return new HelloSpring("luban", "man");
4 } else if (type.equals("B")) {
5 return new HelloSpring("diaocan", "woman");
6 } else {
7 throw new IllegalArgumentException("type must A or B");
8 }
9 }
1 <bean class="com.tuling.spring.DriverFactoryBean">
2 <property name="jdbcUrl" value="jdbc:mysql://localhost:3306"/>
3 </bean>
1 public class DriverFactoryBean implements FactoryBean {
2 private String jdbcUrl;
3 public Object getObject() throws Exception {
4 return DriverManager.getDriver(jdbcUrl);
5 }
6 public Class<?> getObjectType() {
7 return Driver.class;
8 }
9 public boolean isSingleton() {
10 return true;
11 }
12 public String getJdbcUrl() {
13 return jdbcUrl;
14 }
15 public void setJdbcUrl(String jdbcUrl) {
16 this.jdbcUrl = jdbcUrl;
17 }
18 }
a、作?范圍
很多時候Bean對象是?狀態的 ,?有些?是有狀態的 ?狀態的對象我們采?單例即可,?有
狀態則必須是多例的模式,通過scope 即可創建
scope=“prot ot ype”
scope=“singlet on”
如果?個Bean設置成 prot ot ype 我們可以 通過BeanFact oryAware 獲取 BeanFact ory 對象
即可每次獲取的都是新對像。
b、?命周期
Bean對象的創建、初始化、銷毀即是Bean的?命周期。通過 init -met hod、dest roymet
hod 屬性可以分別指定期構建?法與初始?法。
如果覺得麻煩,可以讓Bean去實現 Init ializingBean.af t erPropert iesSet ()、
DisposableBean.dest roy()?法。分別對應 初始和銷毀?法
c、加載機制
指示Bean在何時進?加載。設置lazy-init 即可,其值如下:
t rue: 懶加載,即延遲加載
f alse:?懶加載,容器啟動時即創建對象
def ault :默認,采?def ault -lazy-init 中指定值,如果def ault -lazy-init 沒指定就是
f alse
什么時候使?懶加載?
懶加載會容器啟動的更快,??懶加載可以容器啟動時更快的發現程序當中的錯誤 ,選擇哪
?個就看追求的是啟動速度,還是希望更早的發現錯誤,?般我們會選 擇后者。
4、依賴注?
試想IOC中如果沒有依賴注?,那這個框架就只能幫助我們構建?些簡單的Bean,?之前所說
的復雜Bean的構建問題將?法解決,spring這個框架不可能會像現在這樣成功。 spring 中
ioc 如何依賴注?呢。有以下?種?式:
1. set?法注?
2. 構造?法注?
3. ?動注?(byName、byT ype)
4. ?法注?(lookup-met hod)
1、set?法注?
1 scope=“prototype
2 <bean class="com.tuling.spring.HelloSpring" scope="prototype">
3 </bean>
<bean class="com.tuling.spring.HelloSpring" init-method="init" destroymethod="
destroy"></bean>
1
1 <beans xmlns="http://www.springframework.org/schema/beans"
2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
3
4 default-lazy-init="true">
2、構造?法注?
3、?動注?(byName\byT ype\const ruct or)
byName:基于變量名與bean 名稱相同作為依據插?
byT ype:基于變量類別與bean 名稱作
const ruct or:基于IOC中bean 與構造?法進?匹配(語義模糊,不推薦)
4、依賴?法注?(lookup-met hod)
當?個單例的Bean,依賴于?個多例的Bean,?常規?法只會被注??次,如果每次都
想要獲取?個全新實例就可以采?lookup-met hod ?法來實現。
該操作的原理是基于動態代理技術,重新?成?個繼承??標類,然后重寫抽像?法到達注?
?的。
前?說所單例Bean依賴多例Bean這種情況也可以通過實現 Applicat ionCont ext Aware 、
BeanFact oryAware 接?來獲取BeanFact ory 實例,從?可以直接調?get Bean?法獲取新實
例,推薦使?該?法,相?lookup-met hod語義邏輯更清楚?些。
?、IOC 設計原理與實現
<bean class="com.tuling.1 spring.HelloSpring">
2 <property name="fine" ref="fineSpring"/>
3 </bean>
1 <bean class="com.tuling.spring.HelloSpring">
2 <constructor-arg name="fine">
3 <bean class="com.tuling.spring.FineSpring"/>
4 </constructor-arg>
5 </bean>
<bean id="helloSpringAutowireConstructor"
class="com.tuling.spring.HelloSpring" autowire="byName">
1
2 </bean>
1 #編寫一個抽像類
2 public abstract class MethodInject {
3 public void handlerRequest() {
4 // 通過對該抽像方法的調用獲取最新實例
5 getFine();
6 }
7 # 編寫一個抽像方法
8 public abstract FineSpring getFine();
9 }
10 // 設定抽像方法實現
11 <bean id="MethodInject" class="com.tuling.spring.MethodInject">
12 <lookup-method name="getFine" bean="fine"></lookup-method>
13 </bean>
知識點:
1、源碼學習的?標
2、Bean的構建過程
3、BeanFact ory與Applicat ionCont ext區別
1、源碼學習?標:
不要為了讀書?讀書,同樣不要為了閱讀源碼?讀源碼。沒有?的?頭扎進源碼的?森林
當中很快就迷路了。到時就不是我們讀源碼了,?是源碼‘毒’我們。畢竟?個框架是由專業團
隊,歷經N次版本迭代的產物,我們不能指望像讀?本書的?式去閱讀它。 所以必須在讀源碼
之前找到?標。是什么呢?
?家會想,讀源碼的?標不就是為了學習嗎?這種?標太過抽像,?標?法驗證。通常我
們會設定兩類型?標:?種是對源碼進?改造,?如添加修改某些功能,在實現這種?標的過
程當中?然就會慢慢熟悉了解該項?。但然這個難度較?,耗費的成本也?。另?個做法是
??提出?些問題,閱讀源碼就是為這些問題尋找答案。以下就是我們要?起在源碼中尋找答
案的問題:
1. Bean??是如何?產Bean的?
2. Bean的依賴關系是由誰解來決的?
3. Bean??和應?上?的區別?
2、Bean的構建過程
spring.xml ?件中保存了我們對Bean的描述配置,BeanFact ory 會讀取這些配置然后?
成對應的Bean。這是我們對ioc 原理的?般理解。但在深??些我們會有更多的問題?
1. 配置信息最后是誰JAVA中哪個對象承載的?
2. 這些承載對象是誰業讀取XML?件并裝載的?
3. 這些承載對象?是保存在哪??
BeanDefinit ion (Bean定義)
ioc 實現中 我們在xml 中描述的Bean信息最后 都將保存?BeanDefinit ion (定義)對象中,
其中xml bean 與BeanDefinit ion 程?對?的關系。
由此可?,xml bean中設置的屬性最后都會體現在BeanDefinit ion中。如:
演示查看 BeanDefinit ion 屬性結構
BeanDefinit ionRegist ry(Bean注冊器)
在上表中我們并沒有看到 xml bean 中的 id 和name屬性沒有體現在定義中,原因是ID 其作
為當前Bean的存儲key注冊到了BeanDefinit ionRegist ry 注冊器中。name 作為別名key 注冊
到了 AliasRegist ry 注冊中?。其最后都是指向其對應的BeanDefinit ion。
演示查看 BeanDefinit ionRegist ry屬性結構
XML-bean BeanDefinit ion
class beanClassName
scope scope
lazy-init lazyInit
const ruct or-arg Const ruct orArgument
propert y MutablePropertyValues
f act ory-met hod f actoryMethodName
dest roy-met hod Abst ract BeanDefinit ion.dest royMet hodName
init -met hod Abst ract BeanDefinit ion.init Met hodName
aut owire Abst ract BeanDefinit ion.aut owireMode
id
name
????
????
BeanDefinit ionReader(Bean定義讀?。?br/> ?此我們學習了 BeanDefinit ion 中存儲了Xml Bean信息,?BeanDefinit ionRegist er 基于ID
和name 保存了Bean的定義。接下要學習的是從xml Bean到BeanDefinit ion 然后在注冊?
BeanDefinit ionRegist er 整個過程。
上圖中可以看出Bean的定義是由BeanDefinit ionReader 從xml 中讀取配置并構建出
BeanDefinit ionReader,然后在基于別名注冊到BeanDefinit ionRegist er中。
查看BeanDefinit ???? ionReader結構
?法說明:
???? loadBeanDefinit ions(Resource resource)
???? 基于資源裝載Bean定義并注冊?注冊器
???? int loadBeanDefinit ions(St ring locat ion)
???? 基于資源路徑裝載Bean定義并注冊?注冊器
???? BeanDefinit ionRegist ry get Regist ry()
???? 獲取注冊器
???? ResourceLoader get ResourceLoader()
???? 獲取資源裝載器
基于示例演示BeanDefinit ionReader裝載過程
Beanf act ory(bean ??)
有了Bean的定義就相當于有了產品的配?,接下來就是要把這個配?送到??進??產了。
在ioc當中Bean的構建是由BeanFact ory 負責的。其結構如下:
????
1 //創建一個簡單注冊器
2 BeanDefinitionRegistry register = new SimpleBeanDefinitionRegistry();
3 //創建bean定義讀取器
4 BeanDefinitionReader reader = new XmlBeanDefinitionReader(register);
5 // 創建資源讀取器
6 DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
7 // 獲取資源
8 Resource xmlResource = resourceLoader.getResource("spring.xml");
9 // 裝載Bean的定義
10 reader.loadBeanDefinitions(xmlResource);
11 // 打印構建的Bean 名稱
12 System.out.println(Arrays.toString(register.getBeanDefinitionNames());
?法說明:
???? get Bean(St ring)
???? 基于ID或name 獲取?個Bean
???? <T > T get Bean(Class<T > requiredT ype)
???? 基于Bean的類別獲取?個Bean(如果出現多個該類的實例,將會報錯。但可以指定
primary=“t rue” 調整優先級來解決該錯誤 )
???? Object get Bean(St ring name, Object ... args)
???? 基于名稱獲取?個Bean,并覆蓋默認的構造參數
???? boolean isT ypeMat ch(St ring name, Class<?> t ypeT oMat ch)
???? 指定Bean與指定Class 是否匹配
`
以上?法中重點要關注get Bean,當?戶調?get Bean的時候就會觸發 Bean的創建動作,其
是如何創建的呢?
演示基???? 本BeanFactory獲取?個Bean
1 #創建Bean堆棧
2 // 其反射實例化Bean
3 java.lang.reflect.Constructor.newInstance(Unknown Source:-1)
4 BeanUtils.instantiateClass()
5 //基于實例化策略 實例化Bean
6 SimpleInstantiationStrategy.instantiate()
7 AbstractAutowireCapableBeanFactory.instantiateBean()
8 // 執行Bean的實例化方法
9 AbstractAutowireCapableBeanFactory.createBeanInstance()
10 AbstractAutowireCapableBeanFactory.doCreateBean()
11 // 執行Bean的創建
12 AbstractAutowireCapableBeanFactory.createBean()
13 // 緩存中沒有,調用指定Bean工廠創建Bean
14 AbstractBeanFactory$1.getObject()
15 // 從單例注冊中心獲取Bean緩存
16 DefaultSingletonBeanRegistry.getSingleton()
17 AbstractBeanFactory.doGetBean()
Bean創建時序圖:
從調?過程可以總結出以下?點:
1. 調?BeanFact ory.get Bean() 會觸發Bean的實例化。
2. Def ault Singlet onBeanRegist ry 中緩存了單例Bean
3. Bean的創建與初始化是由Abst ract Aut owireCapableBeanFact ory 完成的。
3、BeanFactory 與 ApplicationContext區別
BeanFact ory 看下去可以去做IOC當中的?部分事情,為什么還要去定義?個
Applicat ionCont ext 呢?
Applicat ionCont ext 結構圖
從圖中可以看到 Applicat ionCont ext 它由BeanFact ory接?派??來,因?提供了
BeanFact ory所有的功能。除此之外cont ext包還提供了以下的功能:
1. MessageSource, 提供國際化的消息訪問
2. 資源訪問,如URL和?件
3. 事件傳播,實現了Applicat ionList ener接?的bean
4. 載?多個(有繼承關系)上下? ,使得每?個上下?都專注于?個特定的層次,?如應?
的web層
總結回顧:
BeanDefinit ion
Def ault ResourceLoader
XmlBeanDefinit ionReader
BeanDefinit ionRegist ry
18 // 獲取Bean
19 AbstractBeanFactory.getBean()
20 // 調用的客戶類
21 com.tuling.spring.BeanFactoryExample.main()
BeanFact ory
Def ault List ableBeanFact ory
Aut owireCapableBeanFact ory
Abst ract Aut owireCapableBeanFact ory
Singlet onBeanRegist ry
Def ault Singlet onBeanRegist ry

看完上述內容,你們掌握什么是IOC容器設計理念以及源碼怎么寫的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

ioc
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女