spring篇(三)龍宮尋寶

周培公發表於2020-10-21

IOC容器之BeanFactory

1.什麼是BeanFactory?
顧名思義,就是生產Bean的工廠。基礎型別的IOC容器,可以提供完整的IOC服務支援。
是不是很難理解!!!打個比方BeanFactory就是生產汽車的工廠。你是不是從其他的汽車零件廠或者自己生產的零配件送到最後的組裝線上啊!最後是不是在生產線的終點取得成品的汽車。類似的,你只要把所需的所有業務物件交給BeanFactroy,剩下的就是直接從BeanFactroy取得最終完成組裝並且可以使用的物件。
2.有了BeanFactory的前後變化?
主要是物件之間依賴關係的解決方式改變了。
之前:系統業務物件需要什麼樣依賴的業務物件就自己去“拿”(想要什麼自己去取)
有了之後:需要什麼樣的依賴讓BeanFactory給送過來。
3.BeanFactory的物件註冊與依賴注入繫結的方式有哪幾種?
3.1 直接編碼方式
在這裡插入圖片描述

public class BeanFactoryTest extends TestCase {
    /**
     * 直接編碼方式
     */
    public void testRedirectCode() {
        DefaultListableBeanFactory beanRegistry = new DefaultListableBeanFactory();
        BeanFactory beanFactory = bindViaCode(beanRegistry);
        Coder coder = (Coder) beanFactory.getBean("coder");
        coder.getApp().say();
 
        /**
         * 輸出為:
         * //通過構造方法注入的情況
         * 呼叫App無參構造
         * 呼叫Coder有參構造,引數app為:App{says='App'}
         * App.say():App
         *
         * //通過setter方式注入的情況下
         * 呼叫Coder無參構造
         * 呼叫App無參構造
         * 呼叫Coder.setApp(), 引數app為: App{says='App'}
         * App.say():App
         */
    }
 
    public static BeanFactory bindViaCode(BeanDefinitionRegistry registry){
        AbstractBeanDefinition appBeanDefinition = new RootBeanDefinition(App.class);
        AbstractBeanDefinition coderBeanDefinition = new RootBeanDefinition(Coder.class);
 
        //將beanDefinition註冊到容器中
        registry.registerBeanDefinition("app", appBeanDefinition);
        registry.registerBeanDefinition("coder", coderBeanDefinition);
 
        //指定依賴關係
        //1、可以通過構造方法注入
//        ConstructorArgumentValues argumentValues = new ConstructorArgumentValues();
//        argumentValues.addIndexedArgumentValue(0, appBeanDefinition);
//        coderBeanDefinition.setConstructorArgumentValues(argumentValues);
 
        //2、可以通過setter方法注入
        MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();
        mutablePropertyValues.addPropertyValue("app", appBeanDefinition);
        coderBeanDefinition.setPropertyValues(mutablePropertyValues);
 
        //繫結完成
        return (BeanFactory)registry;
    }
}

3.2 外部配置檔案方式
(i)XML檔案格式
(ii)Properties檔案格式
在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
        http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
 
    <bean id="app" class="com.me.sourcecode.bean.App"></bean>
 
    <!--<bean id="coder" class="com.me.sourcecode.bean.Coder">-->
        <!--<constructor-arg index="0">-->
            <!--<ref bean="app" />-->
        <!--</constructor-arg>-->
    <!--</bean>-->
 
    <bean id="coder" class="com.me.sourcecode.bean.Coder">
        <property name="app" ref="app"></property>
    </bean>
</beans>

3.3註解方式
4.BeanFactory的XML
4.1< beans >和< bean >
所有註冊到容器的業務物件,在spring中統稱為bean。
在XML中把這些< bean >的元素組織起來,就叫做 < beans >
在這裡插入圖片描述
< description >:在配置檔案中指定一些描述性的資訊。
< import >:載入主要配置檔案時,用< import >元素對其所依賴的配置檔案進行引用。
比如,如果A.xml中的< bean >可能依賴與B.xml中< bean >的某些定義,那麼就可以在A.xml中使用< inport >將B.xml引入到A.xml< import resource=“B.xml”/ >
< alias>:通過< alias >為某些< bean >起一些“外號”,通常情況是為了減少輸入。
4.2 < bean >
id屬性: < bean >在容器中的標誌。
class屬性:每個註冊到容器的物件都需要通過< bean >的class屬性指定其型別。
5.spring在IOC容器的XML配置中,如何表達依賴性?
5.1通過構造方法注入XML
需要使用< constructor-arg>(constructor 建構函式)

public UserDaoImpl(String name){
    this.name = name;
}
<bean id="userDao" class="com.spring.firstday.UserDaoImpl" destroy-method="">
    <constructor-arg name="name" value="Hello"></constructor-arg>
</bean>

當無法明確配置項與物件的構造方法引數列表一一對應時,就需要引入< constructor-arg> 的type(型別)或者index(性質)屬性。
5.1.1 type屬性

public class ConstructorConfusion {  
 
public ConstructorConfusion(String someValue) {  
 
        System.out.println("ConstructorConfusion(String) called");  
 
    }  
 
public ConstructorConfusion(int someValue) {  
 
        System.out.println("ConstructorConfusion(int) called");  
 
    }  
 
}  

該類宣告瞭兩個構造方法,但是注意的是這兩個建構函式名一樣,這個時候就需要type來區別配置

<bean id="constructorConfusion" class="com.apress.prospring.ch4.ConstructorConfusion">   

    <constructor-arg>   

        <value>90</value>   

    </constructor-arg>   

</bean>   

這樣的話spring只呼叫第一個構造方法。

<bean id="constructorConfusion" class="com.apress.prospring.ch4.ConstructorConfusion">   

    <constructor-arg type="int">   

        <value>90</value>   

    </constructor-arg>   

</bean>  

 

5.1.2 index屬性
當只有一個建構函式,但是它的引數型別都相同的時候,就需要index來區分

public class ConstructorConfusion {  
 
public ConstructorConfusion(String someValue1, String sone Value2) {  
 
        System.out.println("ConstructorConfusion(String) called");   
        System.out.println("ConstructorConfusion(String) called");   
 
    }  
 
}  
<bean id="constructorConfusion" class="com.apress.prospring.ch4.ConstructorConfusion">   

    <constructor-arg index="1">  <value>90</value>   
   <constructor-arg index="2">  <value>100</value>   

    
</bean>  

5.2 setter注入
需要使用< property>
< property >有一個name屬性,用來指定該< property >將會注入的物件所對應的例項變數名稱。之後通過value或者ref屬性或者內嵌其他元素來指定具體的依賴物件引用或值。

<bean id="constructorConfusion" class="com.apress.prospring.ch4.ConstructorConfusion">   
  
  <property name = "newListener">
    <ref bean = "djNewsListener"/>
    
    </property> 
</bean>

相關文章