Spring | 基礎(chǔ)

加入架包

  • spring-beans-5.0.7.RELEASE.jar
  • spring-context-5.0.7.RELEASE.jar
  • spring-core-5.0.7.RELEASE.jar
  • spring-expression-5.0.7.RELEASE.jar
  • commons-logging-1.2.jar

1. IOC和DI

  • IOC:控制反轉(zhuǎn)糟红,其思想是反轉(zhuǎn)資源獲取的方向题涨,傳統(tǒng)的資源查找方式要求組件向容器發(fā)起請(qǐng)求查找資源,作為回應(yīng)模她,容器適時(shí)的返回資源解寝。而應(yīng)用了 IOC 之后,則是容器主動(dòng)地將資源推送給它所管理的組件,組件所要做的僅是選擇一種合適的方式來接受資源酸钦。這種行為也被稱為查找的被動(dòng)形式。

  • DI:依賴注入咱枉,IOC的另一種表述方式卑硫,即組件以一些預(yù)先定義好的方式(setter方法)接受來自容器的資源注入徒恋。

圖解

可見,有了IOC容器之后欢伏,對(duì)象的創(chuàng)建都是在容器中進(jìn)行入挣,用戶所要做的只是從容器中獲取已經(jīng)創(chuàng)建好的對(duì)象而已

2. 配置Bean

2.1 Bean 的配置方法

2.1.1 在 xml 文件中通過全類名(反射)來配置 Bean

<bean id="helloWorld2" class="edu.just.spring.beans.HelloWorld"></bean>

class:bean 的全類名, 通過反射的方式在 IOC 容器中創(chuàng)建 Bean, 所以要求 Bean 中必須有無參的構(gòu)造器
id:標(biāo)識(shí)容器中的 bean. id 唯一.

2.1.2 在 xml 中通過靜態(tài)工廠方法來配置 Bean
調(diào)用靜態(tài)工廠方法創(chuàng)建 Bean 是將對(duì)象創(chuàng)建的過程封裝到靜態(tài)方法中,當(dāng)客戶端需要對(duì)象時(shí)硝拧,只需要簡單地調(diào)用靜態(tài)方法径筏,而不用關(guān)心創(chuàng)建對(duì)象的細(xì)節(jié)

創(chuàng)建 Bean 實(shí)例

public class Car {

    private String brand;
    private String corp;
    private double price;
    
    public Car(String brand, String corp, double price) {
        this.brand = brand;
        this.corp = corp;
        this.price = price;
    }

}
/**
 * 靜態(tài)工廠方法: 只要調(diào)用某一個(gè)類的靜態(tài)方法就可以返回 Bean 的實(shí)例
 */
public class StaticCarFactory {

    private static Map<String, Car> cars = new HashMap<>();
    
    static {
        cars.put("audi", new Car("audi", "xixi", 2000));
        cars.put("ford", new Car("ford", "hello", 401111));
    }
    
    public static Car getCar(String name) {
        return cars.get(name);
    }
    
}

配置 Bean:
class 屬性:指向靜態(tài)工廠方法的全類名
factory-method:指向靜態(tài)工廠方法的名字
constructor-arg:如果工廠方法需要傳入?yún)?shù), 則用 constructor-arg 來配置參數(shù)

<bean id="car1" class="edu.just.spring.beans.factory.StaticCarFactory" factory-method="getCar">
    <constructor-arg value="audi"></constructor-arg>
</bean>

結(jié)果:

Car [brand=audi, corp=xixi, price=2000.0]


2.1.3 在 xml 中通過實(shí)例工廠方法配置 Bean
將對(duì)象的創(chuàng)建過程封裝到另一個(gè)對(duì)象實(shí)例的方法中,當(dāng)客戶端需要請(qǐng)求對(duì)象時(shí)障陶,只需要簡單的調(diào)用該實(shí)例方法而不需要關(guān)系對(duì)象的創(chuàng)建細(xì)節(jié)

/**
 * 實(shí)例工廠方法: 實(shí)例工廠的方法, 即需要?jiǎng)?chuàng)建工廠本身, 在調(diào)用工廠的實(shí)例方法來返回 bean 的實(shí)例
 */
public class InstanceCarFactory {

    private Map<String, Car> cars = null;
    
    public InstanceCarFactory() {
        cars = new HashMap<>();
        cars.put("audi", new Car("audi", "xixi", 20000));
        cars.put("ford", new Car("ford", "hha", 30000));
    }
    
    public Car getCar(String name) {
        return cars.get(name);
    }
}

配置 Bean:
factory-bean :指向?qū)嵗S方法的 Bean
factory-method :指向?qū)嵗S方法的名字
constructor-arg:如果工廠方法需要傳入?yún)?shù), 則用 constructor-arg 來配置參數(shù)

<!-- 配置工廠的實(shí)例 -->
<bean id="carFactory" class="edu.just.spring.beans.factory.InstanceCarFactory"></bean>

<bean id="car2" factory-bean="carFactory" factory-method="getCar">
    <constructor-arg value="ford"></constructor-arg>
</bean>

結(jié)果:

Car [brand=ford, corp=hha, price=30000.0]


2.1.4 實(shí)現(xiàn) FactoryBean 接口配置 Bean

  • Spring 中有兩種類型的 Bean滋恬,一種是普通 Bean,另一種是工廠 Bean抱究,即 FactoryBean
  • 工廠 Bean 跟普通 Bean 不同夷恍,其返回的對(duì)象不是指定類的一個(gè)實(shí)例,而是該工廠 Bean 的 getObject 方法所返回的對(duì)象
//自定義的 FactoryBean 需要實(shí)現(xiàn) FactoryBean 接口
public class CarFactoryBean implements FactoryBean<Car>{
    
    private String brand;
    
    public void setBrand(String brand) {
        this.brand = brand;
    }
    
    //返回 Bean 的對(duì)象
    @Override
    public Car getObject() throws Exception {
        return new Car(brand, 500000);
    }

    //返回 Bean 的類型
    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

配置 Bean:
通過 FactoryBean 來配置 Bean 的實(shí)例
class:指向 FactoryBean 的全類名
property:配置 FactoryBean 的屬性

但實(shí)際返回的實(shí)例卻是 FactoryBean 的 getObject() 方法返回的實(shí)例

<bean id="carFactoryBean" class="edu.just.spring.beans.FactoryBean.CarFactoryBean">
    <property name="brand" value="audi"></property>
</bean>

結(jié)果:

Car [brand=audi, price=500000.0]



2.1.5 基于注解的方式來配置 Bean

2.2 ApplicationContext

在Spring IOC 容器讀取 Bean 配置創(chuàng)建 Bean 實(shí)例之前媳维,必須對(duì)它進(jìn)行實(shí)例化酿雪。只有在容器實(shí)例化之后,才可以從 IOC 容器里獲取 Bean 實(shí)例并使用侄刽。Spring 提供了兩種類型的 IOC 容器實(shí)現(xiàn)

  • BeanFactory:IOC 容器的基本實(shí)現(xiàn)
  • ApplicationContext:提供了更多的高級(jí)特性指黎,是 BeanFactory 的子接口

BeanFactory 是 Spring 框架的基礎(chǔ)設(shè)施,面向 Spring 本身
ApplicationContext 面向使用 Spring 框架的開發(fā)者州丹,幾乎所有應(yīng)用場(chǎng)合都直接使用 ApplicationContext 而非底層的 BeanFactory

public class Main {
    public static void main(String[] args) {
        //1. 創(chuàng)建 Spring 得 IOC 容器對(duì)象
        //ApplicationContext 代筆 IOC 容器
        //ClassPathXmlApplicationContext: 是 ApplicationContext 接口的實(shí)現(xiàn)類, 該實(shí)現(xiàn)類從類路徑下來加載配置文件.
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        //2. 對(duì) IOC 容器中獲取 Bean 實(shí)例
        //利用 id 定位到 IOC 容器中的 bean
        HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld2");
    
        //利用類型返回 IOC 容器中的 Bean, 但要求 IOC 容器中必須只能有一個(gè)該類型的 Bean
//      HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
        System.out.println(helloWorld);
    
//      //3. 調(diào)用方法
//      helloWorld.hello();
    }
}


2.3 依賴注入的方式

屬性注入:即通過 setter 方法注入 Bean 的屬性值或依賴的對(duì)象醋安。屬性注入是實(shí)際應(yīng)用中最常用的注入方式

<bean id="helloWorld2" class="edu.just.spring.beans.HelloWorld">
    <property name="name" value="Spring"></property>
</bean>



構(gòu)造器注入:通過構(gòu)造方法注入 Bean 的屬性值或依賴的對(duì)象,它保證了 Bean 實(shí)例在實(shí)例化之后就可以使用墓毒。構(gòu)造器注入在 <constructor-arg> 元素里面聲明屬性吓揪,<constructor-arg> 中沒有 name 屬性

<!-- 通過構(gòu)造方法來配置 bean 的屬性 -->
<bean id="car1" class="edu.just.spring.beans.Car">
    <constructor-arg value="nihao" index="0"></constructor-arg>
    <constructor-arg value="baoma" index="1"></constructor-arg>
    <constructor-arg value="200000" type="double"></constructor-arg>
</bean>


2.4 注入屬性值細(xì)節(jié)

字面值:可用字符串表示的值,可以通過 <value>200</value> 元素標(biāo)簽或 value="nihao" 屬性進(jìn)行注入所计。
PS:若字面值中包含特殊字符柠辞,可以使用 <![CDATA[]]>把字面值包裹

引用其他 Bean:在 Bean 的配置文件中,可以通過 <ref> 元素或者 ref 屬性為 Bean 的屬性或者構(gòu)造器參數(shù)指定對(duì) Bean 的引用

<bean id="car1" class="edu.just.spring.beans.Car"></bean>

<bean id="person" class="edu.just.spring.beans.Person">
    <property name="name" value="Tom"></property>
    <property name="age" value="25"></property>
    <!-- 可以使用 property 的 ref 屬性建立 bean 之間的引用關(guān)系 -->
    <property name="car" ref="car1"></property>
    
    <!-- 通過 ref 屬性添加引用 -->
    <property name="car">
        <ref bean="car1"/>
    </property>
    
    <!-- 內(nèi)部 Bean, 不能被外部引用, 只能在內(nèi)部使用 -->
    <property name="car">
        <bean class="edu.just.spring.beans.Car">
            <constructor-arg value="Ford"></constructor-arg>
            <constructor-arg value="Changan"></constructor-arg>
            <constructor-arg value="200000"></constructor-arg>
        </bean>
    </property>
</bean>

內(nèi)部 Bean:內(nèi)部 Bean 聲明直接包含在 <poperty> 或者 <constructor-arg> 元素里主胧,不需要設(shè)置任何 id 或 name 屬性叭首。同時(shí)內(nèi)部 Bean 不能使用在其他任何地方

集合屬性:在 Spring 中可以通過一組內(nèi)置的 xml 標(biāo)簽,如 <list>踪栋、<set>焙格、<map>

  • list 標(biāo)簽
<!-- 測(cè)試如何配置集合屬性 -->
<bean id="person3" class="edu.just.spring.beans.collections.Person">
    <property name="name" value="Mike"></property>
    <property name="age" value="20"></property>
    <property name="cars">
        <!-- 使用 list 節(jié)點(diǎn)為 List 類型的屬性賦值 -->
        <list>
            <ref bean="car1"/>
            <ref bean="car2"/>
            <!-- 可以指定內(nèi)部 Bean -->
            <bean class="edu.just.spring.beans.Car">
                <constructor-arg value="Ford"></constructor-arg>
                <constructor-arg value="Changan"></constructor-arg>
                <constructor-arg value="200000"></constructor-arg>
            </bean>
        </list>
    </property>
</bean>
  • map 標(biāo)簽
<!-- 配置 Map 屬性值 -->
<bean id="newPerson" class="edu.just.spring.beans.collections.Person2">
    <property name="name" value="Rose"></property>
    <property name="age" value="29"></property>
    <property name="cars">
        <!-- 使用 map 節(jié)點(diǎn) 的 entry 子節(jié)點(diǎn)配置 Map 類型的成員變量 -->
        <map>
            <entry key="AA" value-ref="car1"></entry>
            <entry key="BB" value-ref="car2"></entry>
        </map>
    </property>
</bean>
  • property 標(biāo)簽
<bean id="dataSource" class="edu.just.spring.beans.collections.DataSource">
    <property name="properties">
        <!-- 使用 props 和 prop 子節(jié)點(diǎn)為 Properties 屬性賦值 -->
        <props>
            <prop key="user">root</prop>
            <prop key="password">password</prop>
            <prop key="jdbcUrl">jdbc:mysql:///test</prop>
            <prop key="driverClass">com.mysql.jdbc.Driver</prop>
        </props>
    </property>
</bean>


使用utility scheme定義集合
使用基本的集合標(biāo)簽定義集合時(shí),不能將集合作為獨(dú)立的 Bean 定義,導(dǎo)致其他 Bean 無法引用該集合,所以無法在不同 Bean 直接共享集合

<!-- 配置獨(dú)立的集合 bean, 以供多個(gè) bean 進(jìn)行引用 -->
 <util:list id="cars">
    <ref bean="car1"/>
    <ref bean="car2"/>
 </util:list>
    
<bean id="person4" class="edu.just.spring.beans.collections.Person">
    <property name="name" value="Jack"></property>
    <property name="age" value="100"></property>
    <property name="cars" ref="cars"></property>
</bean>


使用 p 命名空間

<!-- 通過 p 命名空間為 bean 的屬性賦值, 需要先導(dǎo)入 p 命名空間, 相對(duì)于傳統(tǒng)的配置方式更加的簡潔. -->
<bean id="person5" class="edu.just.spring.beans.collections.Person" p:name="luwenhe"
    p:age="20" p:cars-ref="car1"></bean>


2.5 自動(dòng)裝配

Spring IOC 容器可自動(dòng)裝配 Bean九串,需要做的僅僅是在 <bean> 的 autowire 屬性里指定自動(dòng)裝配的模式

可以使用 autowire 屬性指定 自動(dòng)裝配 的方式.
byName:根據(jù) bean 的名字(id 的 值)和當(dāng)前 bean 的 setter 風(fēng)格的屬性名進(jìn)行自動(dòng)裝配生棍,若有匹配的冬阳,則進(jìn)行自動(dòng)裝配荣瑟,若沒有匹配的,則不裝配
byType:根據(jù) bean 的類型和當(dāng)前 bean 的屬性的類型進(jìn)行自動(dòng)裝配摩泪,若 IOC 容器中有 1 個(gè)以上的類型匹配的 bean,則拋出異常

缺點(diǎn):如果只希望裝配個(gè)別屬性時(shí), autowire 就不夠靈活劫谅,autowire 屬性要么根據(jù)類型自動(dòng)裝配, 要么根據(jù)名稱自動(dòng)裝配, 不能兩者兼而有之见坑。在實(shí)際項(xiàng)目中很少使用自動(dòng)裝配功能, 因?yàn)楹妥詣?dòng)裝配功能所帶來的好處比起來, 明確清晰的配置文檔更加具有說服力

<bean id="person" class="edu.just.spring.beans.autowire.Person" p:name="Tim"
    autowire="byName"></bean>
        
<bean id="person" class="edu.just.spring.beans.autowire.Person" p:name="Tim"
    autowire="byType"></bean>


2.6 Bean 之間的關(guān)系:繼承、依賴

  • 被繼承的 Bean 成為父 Bean捏检。繼承這個(gè)父 Bean 的 Be'an 稱為子 Bean
  • 子 Bean 繼承父 Bean 的配置荞驴,也可以覆蓋從父 Bean 繼承過來的配置
  • 若只想把父 Bean 作為模板,可以設(shè)置 <bean> 的 abstract 屬性為 true
  • 也可以忽略父 Bean 的 class 屬性贯城,讓子 Bean 指定自己的類熊楼。此時(shí) abstract 必須設(shè)置為 true
<!-- 
    抽象 bean: bean 的 abstract 屬性為 true 的 bean. 這樣的 bean 不能被 IOC 容器實(shí)例化, 只用來被繼承配置 
    若某一個(gè) bean 的 class 屬性沒有指定, 則該 bean 必須是一個(gè)抽象 bean
-->
<bean id="address" p:city="Beijing^^" p:street="WuDAOkOU" abstract="true"></bean>
    
<!-- bean 配置的繼承: 使用 bean 的 parent 屬性指定繼承哪個(gè) bean 的配置 -->
<bean id="address2" class="edu.just.spring.beans.autowire.Address"
    p:street="DaZhongSi" parent="address"></bean>
    
<bean id="car" class="edu.just.spring.beans.autowire.Car"
    p:brand="BenChi" p:price="100000"></bean>
     
<!-- 要求在配置 Person 時(shí), 必須有一個(gè)關(guān)聯(lián)的 car! 即 person 這個(gè) bean 依賴于 Car 這個(gè) bean -->
<bean id="person" class="edu.just.spring.beans.autowire.Person"
    p:name="Tom" p:address-ref="address2" depends-on="car"></bean>
  • Spring 允許用戶通過 depend-on 屬性設(shè)定 Bean 前置依賴的 Bean,前置依賴 Bean 會(huì)在本 Bean 實(shí)例化之前創(chuàng)建好

2.7 Bean 的作用域

Spring 可以在 <bean> 元素的 scope 屬性里設(shè)置 Bean 的作用域

  • singleton:默認(rèn)值, 容器初始化時(shí)創(chuàng)建 bean 實(shí)例, 在整個(gè)容器的生命周期內(nèi)只創(chuàng)建這一個(gè) bean, 是單例的
  • prototype:原型的, 容器初始化時(shí)不創(chuàng)建 bean 的實(shí)例, 而在每次請(qǐng)求時(shí)都創(chuàng)建一個(gè)新的 Bean 實(shí)例, 并返回
<bean id="car" class="edu.just.spring.beans.autowire.Car" scope="prototype">
    <property name="brand" value="Audi"></property>
    <property name="price" value="20000"></property>
</bean>

<b/>

2.8 使用外部屬性文件

db.properties:

user=root
password=lwh011305
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/fileupload?useSSL=true

導(dǎo)入屬性文件:

<!-- 導(dǎo)入屬性文件 -->
<context:property-placeholder location="classpath:db.properties"/>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <!-- 使用外部化屬性文件的屬性 -->
    <property name="user" value="${user}"></property>
    <property name="password" value="${password}"></property>
    <property name="driverClass" value="${driverClass}"></property>
    <property name="jdbcUrl" value="${jdbcUrl}"></property>
</bean>


2.9 Spring 表達(dá)式語言:SpEL

類似于 EL:SpEL 使用 #{...} 作為定界符能犯,所以在大框號(hào)中的字符被認(rèn)為是 SpEL

為屬性賦一個(gè)字面量:

<bean id="address" class="edu.just.spring.beans.spel.Address">
    <!-- 使用 spel 為屬性賦一個(gè)字面值 -->
    <property name="city" value="#{'beijing'}"></property>
    <property name="street" value="wudaokou"></property>
</bean>

使用 SpEL 引用類的靜態(tài)屬性:

<bean id="car" class="edu.just.spring.beans.spel.Car">
    <property name="brand" value="Audi"></property>
    <property name="price" value="2000"></property>
    <!-- 使用 Spel 引用類的靜態(tài)屬性 -->
    <property name="tyrePerimeter" value="#{T(java.lang.Math).PI * 80}"></property>
</bean>

使用 SpEL 來引用其他 Bean

<bean id="person" class="edu.just.spring.beans.spel.Person">
    <property name="name" value="luwenhe"></property>
    
    <!-- 使用 Spel 來引用其他的 Bean 的屬性 -->
    <property name="city" value="#{address.city}"></property>
        
    <!-- 使用 Spel 來引用其他的 Bean -->
    <property name="car" value="#{car}"></property>
        
    <!-- 使用 Spel 中使用運(yùn)算符 -->
    <property name="info" value="#{car.price > 30000 ? '金領(lǐng)' : '白領(lǐng)'}"></property>
</bean>


2.10 IOC 容器中 Bean 的生命周期方法

Spring IOC 容器對(duì) Bean 的生命周期進(jìn)行管理的過程:

  • 通過構(gòu)造器或者工廠方法創(chuàng)建 Bean 實(shí)例
  • 為 Bean 的屬性設(shè)置值和對(duì)其他 Bean 的引用
  • 調(diào)用 Bean 的初始化方法
  • Bean 可以使用了
  • 當(dāng)容器關(guān)閉時(shí)鲫骗,調(diào)用了 Bean 的銷毀方法

創(chuàng)建 Bean 方法

public class Car {

    public Car() {
        System.out.println("Car's Constructor ... ");
    }
    
    private String brand;
    
    public void setBrand(String brand) {
        System.out.println("setBrand ... ");
        this.brand = brand;
    }
    
    public String getBrand() {
        return brand;
    }
    
    public void init() {
        System.out.println("init ... ");
    }
    
    public void destory() {
        System.out.println("destroy ... ");
    }

    @Override
    public String toString() {
        return "Car [brand=" + brand + "]";
    }
}

為 Bean 設(shè)置屬性值:init-methoddestory-method 屬性為 Bean 指定初始化和銷毀方法

<bean id="car1" class="edu.just.spring.beans.cycle.Car"
    init-method="init" destroy-method="destory">
    <property name="brand" value="Audi"></property>
</bean>

調(diào)用 Bean 的初始化方法

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-cycle.xml");
        
Car car = (Car) ctx.getBean("car1");
System.out.println(car);
        
ctx.close();

輸出:

Car's Constructor ... 
setBrand ... 
init ... 
Car [brand=Audi]
六月 28, 2018 5:24:15 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@6438a396: startup date [Thu Jun 28 17:24:14 CST 2018]; root of context hierarchy
destroy ... 


創(chuàng)建 Bean 的后置處理器

  • Bean 后置處理器允許在調(diào)用初始化方法前后對(duì) Bean 進(jìn)行額外處理
  • Bean 后置處理器對(duì) IOC 容器里的所有 Bean 實(shí)例逐一處理,而非單一實(shí)例
  • 需要實(shí)現(xiàn) BeanPostProcessor 接口

Spring IOC 容器對(duì) Bean 的生命周期進(jìn)行管理的過程

  • 通過構(gòu)造器或者工廠方法創(chuàng)建 Bean 實(shí)例
  • 為 Bean 的屬性設(shè)置值和對(duì)其他 Bean 的引用
  • 將 Bean 實(shí)例傳遞給 Bean 后置處理器的 postProcessBeforeInitialization 方法
  • 調(diào)用 Bean 的初始化方法
  • 將 Bean 實(shí)例傳遞給 Bean 后置處理器的 postProcessAfterInitialization 方法
  • Bean 可以使用
  • 當(dāng)容器關(guān)閉時(shí)踩晶,調(diào)用 Bean 的銷毀方法

實(shí)現(xiàn) BeanPostProcessor 接口:
bean:bean 實(shí)例本身
beanName:IOC 容器配置的 bean 的名字.
返回值:是實(shí)際上返回給用戶的那個(gè) Bean执泰,注意:可以在以上兩個(gè)方法中修改返回的 Bean,甚至返回一個(gè)新的 Bean

public Object postProcessBeforeInitialization(Object bean, String beanName):init-method 之前被調(diào)用
public Object postProcessAfterInitialization(Object bean, String beanName):init-method 之后被調(diào)用的實(shí)現(xiàn)

public class MyBeanPostProcessor implements BeanPostProcessor{
        
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization: " + bean + ", " + beanName);
        
        if("car".equals(beanName)) {
            //..
        }
        
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization: " + bean + ", " + beanName);
    
        Car car = new Car();
        car.setBrand("Ford");
        return car;
    }
} 

配置 Bean

<!-- 配置 Bean 的后置處理器: 不需要配置 id, IOC 容器自動(dòng)識(shí)別是一個(gè) BeanPostProcessor -->
<bean class="edu.just.spring.beans.cycle.MyBeanPostProcessor"></bean>

輸出:

Car's Constructor ... 
setBrand ... 
postProcessBeforeInitialization: Car [brand=Audi], car1
init ... 
postProcessAfterInitialization: Car [brand=Audi], car1
Car's Constructor ... 
setBrand ... 
Car [brand=Ford]
六月 28, 2018 5:53:28 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@6438a396: startup date [Thu Jun 28 17:53:27 CST 2018]; root of context hierarchy
destroy ... 


2.11 泛型依賴注入

泛型依賴注入:子類之間的依賴關(guān)系由其父類泛型以及父類之間的依賴關(guān)系來確定渡蜻,父類的泛型必須為同一類型

BaseRepository 類

public class BaseRepository<T> {}

UserRepository 類:標(biāo)識(shí)持久層

@Repository
public class UserRepository extends BaseRepository<User>{}

BaseService 類:通過 Autowired 自動(dòng)裝配 BaseRepository 實(shí)例

public class BaseService<T> {

    @Autowired
    protected BaseRepository<T> repository;
    
    public void add() {
        System.out.println("add ...");
        System.out.println(repository);
    }
    
}

UserService 類:通過父類的泛型實(shí)例术吝,在 UserService 中已經(jīng)注入了 UserRepository 實(shí)例

@Service
public class UserService extends BaseService<User>{}

輸出:

add ...
edu.just.spring.beans.generic.di.UserRepository@799d4f69
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市茸苇,隨后出現(xiàn)的幾起案子排苍,更是在濱河造成了極大的恐慌,老刑警劉巖学密,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淘衙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡腻暮,警方通過查閱死者的電腦和手機(jī)幔翰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來西壮,“玉大人遗增,你說我怎么就攤上這事】钋啵” “怎么了做修?”我有些...
    開封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我饰及,道長蔗坯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任燎含,我火速辦了婚禮宾濒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屏箍。我一直安慰自己绘梦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開白布赴魁。 她就那樣靜靜地躺著卸奉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪颖御。 梳的紋絲不亂的頭發(fā)上榄棵,一...
    開封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音潘拱,去河邊找鬼疹鳄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛芦岂,可吹牛的內(nèi)容都是我干的尚辑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼盔腔,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼杠茬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弛随,我...
    開封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤瓢喉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后舀透,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栓票,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年愕够,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了走贪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惑芭,死狀恐怖坠狡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情遂跟,我是刑警寧澤逃沿,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布婴渡,位于F島的核電站,受9級(jí)特大地震影響凯亮,放射性物質(zhì)發(fā)生泄漏边臼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一假消、第九天 我趴在偏房一處隱蔽的房頂上張望柠并。 院中可真熱鬧,春花似錦富拗、人聲如沸臼予。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至葵擎,卻和暖如春谅阿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酬滤。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來泰國打工签餐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盯串。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓氯檐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親体捏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冠摄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本來是準(zhǔn)備看一看Spring源碼的。然后在知乎上看到來一個(gè)帖子几缭,說有一群**自己連Spring官方文檔都沒有完全讀...
    此魚不得水閱讀 6,935評(píng)論 4 21
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器河泳,...
    simoscode閱讀 6,717評(píng)論 2 22
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)年栓,斷路器拆挥,智...
    卡卡羅2017閱讀 134,664評(píng)論 18 139
  • 內(nèi)容過長,core部分分開發(fā)布某抓,core章節(jié)第二部分點(diǎn)擊:Spring Framework 官方文檔中文版—Cor...
    kopshome閱讀 33,682評(píng)論 7 24
  • 文章作者:Tyan博客:noahsnail.com 3.4 Dependencies A typical ente...
    SnailTyan閱讀 4,166評(píng)論 2 7