Spring中的依賴注入與Bean的配置

前言

我們前面講過如何創建第一個Spring程序,也簡單的接觸了一下Spring中的依賴注入。接着我們看看其中的細節。

如果還不會創建Spring的看我前一篇博文:Spring 概述

如何配置一個Bean

通過bean節點去配置,其中id表示該bean的唯一屬性,class表示該bean的路徑。

    <bean id="personDao" class="com.zxy.ioc.PersonDaoImpl"/>

如何獲取Bean

通常,獲取Bean一共有兩種方式。

  • 通過id獲取
  • 通過類型獲取

id獲取

ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-config.xml");
PersonDao personDao= (PersonDao) applicationContext.getBean("personDao");

類型獲取

ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-config.xml");
PersonDao personDao=applicationContext.getBean(PersonDao.class);

需要注意的是,通過類型獲取Bean有一定的侷限性,當Ioc容器中存在多個類型相同的Bean時,容器將無法判斷你想要哪個Bean從而拋出異常。

而通過id獲取Bean則沒有這樣的問題,因爲每個配置的Bean都對應着一個唯一的id。

屬性注入

屬性注入即通過setter方式對Bean注入屬性值或對象
例如有這樣一個類:

package com.zxy.ioc;

public class HelloWorld {
    private String name;

    public void setName(String name) {
    }

    public String getName() {
        return name;
    }
}

那麼我們對其中的name賦值就通過bean來完成

<bean id="helloWorld" class="com.zxy.ioc.HelloWorld">
        <property name="name" value="Tom"></property>
</bean>

其中name表示屬性名,value表示屬性值

構造方法注入

顧名思義,當然就是給我們的構造方法注入屬性的。我們再來寫一個類:

package com.zxy.ioc;

public class Car {
    private String brand;
    private String corp;
    private int price;

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

我們要對構造方法中的屬性賦值,那麼就要用到constructor-arg節點:

<bean id="car" class="com.zxy.ioc.Car">
        <constructor-arg value="Audi"/>
        <constructor-arg value="ShangHai"/>
        <constructor-arg value="30000"/>
</bean>

如果是這樣配置的話,那麼就是按照先後順序來配置。當然我們也可以指定順序:

<bean id="car" class="com.zxy.ioc.Car">
	<constructor-arg value="Aui" index="1"></constructor-arg>
	<constructor-arg value="ShangHai" index="0"></constructor-arg>
	<constructor-arg value="300000" index="2"></constructor-arg>
</bean>

但是的話這樣有缺陷,比如我把這個類改一下,再試試注入值:

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

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

如果還是像上面那樣去注入值,例如:

<bean id="car" class="com.zxy.ioc.Car">
	<constructor-arg value="Aui"></constructor-arg>
	<constructor-arg value="ShangHai"></constructor-arg>
	<constructor-arg value="300000"></constructor-arg>
</bean>

看起來確實沒什麼問題,但是當我們去獲取這個Bean然後輸出的時候,發現顯示的值並不是預想的那樣:
在這裏插入圖片描述
雖然程序並沒有報錯,但是沒有達到我們預想的那種效果。
所以我們在配置的時候可以把類型順便加上:

<bean id="car" class="com.zxy.ioc.Car">
        <constructor-arg value="Audi" type="java.lang.String"/>
        <constructor-arg value="ShangHai" type="java.lang.String"/>
        <constructor-arg value="30000" type="int"/>
    </bean>

這樣就不會出任何問題了。

屬性注入細節

上面大致的介紹了一下屬性注入,接下來我們來了解一下其中的細節部分;

處理特殊字符

不管是屬性注入還是構造方法注入,都可以通過value進行注入。還可以用value子節點進行注入:

<bean id="car" class="com.zxy.ioc.Car">
	<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
	<constructor-arg value="ShangHai" type="java.lang.String"/>
	<constructor-arg type="int">
		<value>300000</value>
	</constructor-arg>
</bean>

當然,並不會平白無故的多寫個value子節點的。所以他的作用就是處理一些特殊字符:

<bean id="car" class="com.zxy.ioc.Car">
	<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
	<constructor-arg type="java.lang.String">
		<value><![CDATA[<ShangHai>]]></value>
	</constructor-arg>
	<constructor-arg type="int">
		<value>300000</value>
	</constructor-arg>
</bean>

在xml中<>符號屬於特殊字符,需要用![CDATA[]]來完成。

引入其他Bean

我們以前寫組件的時候都會引入其他類型的Bean,在Spring中,要想Bean之間互通,也需要去配置對Bean的引用。

先定義一個Person類:

package com.zxy.ioc;

public class Person {
    private String name;
    private int age;
    private Car car;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }
}

接着添加配置文件

<bean id="person" class="com.zxy.ioc.Person">
        <property name="name" value="Tom"/>
        <property name="age" value="20"/>
        <property name="car" ref="car"/>
    </bean>

前面我們已經配置了一個id爲car的Bean,在配置Person的時候,只需要將car作爲屬性值注入到該Bean的car屬性即可,因爲是一個引用類型,所以需要使用ref屬性進行注入而非value(ref中的值爲需要注入的Bean的id),這裏也可以使用ref子節點進行注入。

你也可以在屬性或構造器裏包含一個Bean的聲明,這樣的Bean稱爲內部Bean,比如:

<bean id="person" class="com.zxy.ioc.Person">
        <property name="name" value="Tom"/>
        <property name="age" value="20"/>
        <property name="car">
            <bean class="com.zxy.ioc.Car">
                <constructor-arg value="Ford"></constructor-arg>
                <constructor-arg value="Beijing"></constructor-arg>
                <constructor-arg value="200000"></constructor-arg>
            </bean>
        </property>
    </bean>

因爲內部Bean是無法提供給外部使用的,所以設不設置id都無所謂了。

Spring還可以通過級聯對屬性賦值:

<bean id="person" class="com.zxy.ioc.Person">
	<property name="name" value="Tom"></property>
	<property name="age" value="24"></property>
	<property name="car" ref="car"></property>
	<property name="car.maxSpeed" value="250"/>
</bean>

注入集合類型

修改一下Person類的代碼:

package com.zxy.ioc;

import java.util.List;

public class Person {
    private String name;
    private int age;
    private List<Car> cars;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<Car> getCar() {
        return cars;
    }

    public void setCar(List<Car> car) {
        this.cars = car;
    }
}

那集合類型的成員變量怎麼進行賦值呢?

<bean id="person" class="com.zxy.ioc.Person">
	<property name="name" value="Mike"></property>
	<property name="age" value="21"></property>
	<property name="cars">
		<list>
			<ref bean="car"/>
			<ref bean="car2"/>
			<ref bean="car3"/>
		</list>
	</property>
</bean>

其實很簡單,首先你需要在配置文件中配置Car,然後通過list子節點注入集合,再通過ref子節點指定集合中的子元素(ref子節點中的bean屬性值爲對應的Bean的id)。

數組的定義和List一樣,都使用list子節點,而Set集合的定義方式和List相同,唯一不同的是Map集合。,Map集合的定義如下:

<bean id="person" class="com.zxy.ioc.person">
	<property name="name" value="Jack"></property>
	<property name="age" value="30"></property>
	<property name="cars">
		<map>
			<entry key="First" value-ref="car"></entry>
			<entry key="Second" value-ref="car2"></entry>
		</map>
	</property>
</bean>

這裏使用map子節點定義Map集合,再通過entry子節點定義集合中的子元素,其中key表示鍵value-ref表示值引用

Properties注入

Properties應用場景最多的是JDBC的操作。
我們先定義一個DataSource類:

package com.zxy.ioc;

import java.util.Properties;

public class DataSource {

    private Properties properties;

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

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

接着配置Bean,值得注意的是,這兒的節點是用的props

<bean id="dataSource" class="com.zxy.ioc.DataSource">
        <property name="properties">
            <props>
                <prop key="user">root</prop>
                <prop key="password">1</prop>
                <prop key="jdbcUrl">jdbc:mysql://localhost:3306/test</prop>
                <prop key="driverClass">com.mysql.jdbc.Driver</prop>
            </props>
        </property>
    </bean>

自動裝配

大家在看前面的部分的時候會發現,Bean之間的聯繫都是我們自己手動去設置。不夠,Spring也爲我們提供了自動配置的方式。
比如現在有這樣的兩個類:

public class Person {
	
	private String name;
	private Address address;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
}

public class Address {
	
	private String city;
	private String street;
	
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getStreet() {
		return street;
	}
	public void setStreet(String street) {
		this.street = street;
	}
}

如果是按照傳統的配置方式相信大家都會寫:

<bean id="address" class="com.zxy.ioc.Address">
	<property name="city" value="BeiJing"></property>
	<property name="street" value="XuanWu"></property>
</bean>

<bean id="person" class="com.zxy.ioc.Person">
	<property name="name" value="Tom"></property>
	<property name="address" ref="address"></property>
</bean>

但是,要如何來實現自動裝配呢?
SpringIoc容器可以自動裝配Bean,需要做的僅僅是在beanautowire屬性裏指定自動裝配的模式,裝配模式有以下幾種:

  • byType:根據類型自動裝配。若IOC容器中有多個與目標Bean類型一致的Bean,在這種情況下,Spring將無法判定哪個Bean最適合該屬性,所以不能執行自動裝配
  • byName:根據名稱自動裝配。必須將目標Bean的名稱和屬性名設置爲完全一致
  • constructor:根據構造器自動裝配。當Bean中存在多個構造器時,該方式將會很複雜,不推薦使用

我們再來修改一下配置文件:

<bean id="address" class="com.zxy.ioc.Address">
	<property name="city" value="BeiJing"></property>
	<property name="street" value="XuanWu"></property>
</bean>

<bean id="person" class="com.zxy.ioc.Person" autowire="byName">
	<property name="name" value="Tom"></property>
</bean>

由於在Person類中有setAddress()方法,所以Spring容器會自動去查找裝配的Bean;
但是這樣做也有壞處:

  • 在Bean配置文件裏設置autowire屬性進行自動裝配將會裝配Bean的所有屬性,然而,若只是希望裝配個別屬性時,autowire屬性就不夠靈活了
  • autowire屬性要麼根據類型自動裝配,要麼根據名稱自動裝配,二者不能混合使用

一般情況下,在實際的項目中很少使用自動裝配功能,因爲和自動裝配功能所帶來的好處比起來,明確清晰的配置文檔更有說服力一些。

Spring Bean的常用配置及屬性

我們上面接觸到了各種類型的注入,當然,肯定不止那麼幾個。bean元素的常用屬性表如下圖所示:
在這裏插入圖片描述

實例化Bean的三種方法

創建SpringDemo02,不使用任何模板
在這裏插入圖片描述
在這裏插入圖片描述
這兒選擇自動導入
在這裏插入圖片描述
接着給項目添加骨架,右鍵項目名稱
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
接下來配置tomcat啥的就不用我多說了。等項目加載完成就能在src目錄下看到spring-config.xml文件。這個就是Spring爲我們生成的配置文件。
在這裏插入圖片描述
接着在src目錄下創建一個名爲com.zxy.bean的包,在包中創建Person1類

package com.zxy.bean;

public class Person1 {
}

就這樣,啥也不寫。我們來看看具體哪三種方法實現實例化:

構造器實例化

這第一種我們之前就已經用過了,就是在配置文件中寫bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <bean id="person1" class="com.zxy.bean.Person1">
    </bean>
</beans>

然後創建一個名爲com.zxy.test的包,並定義一個類InstanceTest1:

package com.zxy.test;

import com.zxy.bean.Person1;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class InstanceTest1 {
    @Test
    void test(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("spring-config.xml");
        Person1 p1= (Person1) ac.getBean("person1");
        System.out.println(p1);
    }
}

我們看看運行結果:
在這裏插入圖片描述
如果運行報錯的,請把spring-config.xml文件放在resources文件夾下。

靜態工廠方式實例化

在Spring中也可以通過靜態工廠方式實現實例化。
1)創建實體類
在項目下創建一個名爲com.zxy.static_factory的包,並在包中創建實體類MyBeanFactory。並在bean包中創建Person2,同樣,Person2不需要寫任何內容。
在這裏插入圖片描述
2)編寫靜態方法

package com.zxy.static_factory;

import com.zxy.bean.Person2;

public class MyBeanFactory {
    static Person2 p2=new Person2();
    public static Person2 createBean(){
        return p2;
    }
}

3)編寫xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <bean id="person1" class="com.zxy.bean.Person1">
    </bean>
    <bean id="person2" class="com.zxy.static_factory.MyBeanFactory"
          factory-method="createBean"></bean>
</beans>

4)編寫測試類

package com.zxy.test;

import com.zxy.bean.Person2;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class InstanceTest2 {
    @Test
    void test(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("spring-config.xml");
        Person2 p2= (Person2) ac.getBean("person2");
        System.out.println(p2);
    }
}

5)運行結果
在這裏插入圖片描述

實例工廠方式實例化

在Spring中,還有一種實例化Bean的方式就是採用實例工廠,工廠類不在使用靜態方法創建Bean的實例,而是直接在成員方法中創建Bean的實例;

同時在配置文件中,需要實例化的Bean也不是通過class指向其實例化類,而是通過factory-bean屬性配置一個實例工廠,然後使用factory-method屬性確定使用工廠中的哪個方法。例如:

1)創建實體類
和前面的Person1、Perosn2一樣,創建一個Person3,不要任何方法體。

2)創建實例工廠類
創建一個子包,名爲factory,在包中創建一個MyBeanFactory類:
在這裏插入圖片描述
添加如下代碼:

package com.zxy.factory;

import com.zxy.bean.Person3;

public class MyBeanFactory {
    Person3 p3=new Person3();
    
    public Person3 createBean(){
        return p3;
    }
}

3)配置spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <bean id="person1" class="com.zxy.bean.Person1">
    </bean>
    <bean id="person2" class="com.zxy.static_factory.MyBeanFactory"
          factory-method="createBean"></bean>

<!--    配置實例工廠-->
    <bean id="myBeanFactory" class="com.zxy.factory.MyBeanFactory"></bean>

<!--    創建factory-bean指向實例工廠-->
    <bean id="person3" class="com.zxy.bean.Person3" factory-bean="myBeanFactory" factory-method="createBean"></bean>
</beans>

上述代碼中首先創建了一個實例工廠,然後配置了實例化的Bean。在id爲person3的Bean中,使用factory-bean指定一個實例工廠,該屬性就是實例工廠中的id屬性值。使用factory-method屬性指向工廠中的createBean()方法。

4)創建測試類

package com.zxy.test;

import com.zxy.bean.Person3;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class InstanceTest3 {
    @Test
    void test(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("spring-config.xml");
        Person3 p3= (Person3) ac.getBean("person3");
        System.out.println(p3);
    }
}

5)運行結果
在這裏插入圖片描述

以上就是三種方式實例化Bean,至於喜歡哪一種,全憑自己喜歡就行。反正挑簡單的來。

Spring Bean的作用域

作用域的種類

Spring容器在初始化一個Bean的實例時,同時會指定該實例的作用域。Spring3爲Bean定義了五種作用域,具體如下:

1)singleton
單例模式下,使用singleton定義的Bean在Spring容器中只有一個實例,這也是Bean默認的作用域。

2)prototype
原型模式下,每次通過Spring容器獲取prototype定義的Bean時,容器將創建一個新的Bean實例。

3)request
每一次HTTP請求中,容器會返回該Bean的同一個實例。而對不同的HTTP請求,會返回不同的實例,該作用域僅在當前HTTP Request內有效。

4)session
在一次HTTP session這種,容器會返回該Bean的一個實例。而對不同的HTTP請求,會返回不同的實例,該作用域僅在當前HTTP session內有效。

5)global Session
在一個全局的 HTTP Session 中,容器會返回該 Bean 的同一個實例。該作用域僅在使用 portlet context 時有效。

在上述五種作用域中,singleton 和 prototype 是最常用的兩種,接下來將對這兩種作用域進行詳細講解。

singleton作用域

singleton 是 Spring 容器默認的作用域,當一個 Bean 的作用域爲 singleton 時,Spring 容器中只會存在一個共享的 Bean 實例,並且所有對 Bean 的請求,只要 id 與該 Bean 定義相匹配,就只會返回 Bean 的同一個實例。

通常情況下,這種單例模式對於無會話狀態的 Bean(如 DAO 層、Service 層)來說,是最理想的選擇。

在 Spring 配置文件中,可以使用<bean>元素的 scope 屬性,將 Bean 的作用域定義成 singleton,其配置方式如下所示:

<bean id="person" class="comzxy.ioc.Person" scope="singleton"/>

在項目SpringDemo2的目錄下創建一個名爲com.zxy.scope的包,在該包下創建Person類。然後按照上述原則配置好spring-config.xml,最後創建一個PersonTest的測試類:
在這裏插入圖片描述

package com.zxy.test;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PersonTest {
    @Test
    void test(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("spring-config.xml");
        // 輸出兩次實例,對比是不是一樣的
        System.out.println(ac.getBean("person"));
        System.out.println(ac.getBean("person"));
    }
}

在這裏插入圖片描述
我們可以發現兩次結果都是一樣的。其實我們不去設置scope=“singleton”的話,默認也是這個。

prototype作用域

使用 prototype 作用域的 Bean 會在每次請求該 Bean 時都會創建一個新的 Bean 實例。因此對需要保持會話狀態的 Bean(如 Struts2 的 Action 類)應該使用 prototype 作用域。

在 Spring 配置文件中,要將 Bean 定義爲 prototype 作用域,只需將 <bean> 元素的 scope 屬性值定義成 prototype,其示例代碼如下所示:

<bean id="person" class="com.zxy.ioc.Person" scope="prototype"/>

將《singleton作用域》部分中的配置文件更改成上述代碼形式後,再次運行 test() 方法,控制檯的輸出結果如圖所示。
在這裏插入圖片描述
從圖可以看出,在prototype作用域下,Spring容器創建了兩個不同的實例。

Spring Bean的生命週期

Spring 容器可以管理 singleton 作用域 Bean 的生命週期,在此作用域下,Spring 能夠精確地知道該 Bean 何時被創建,何時初始化完成,以及何時被銷燬。

而對於 prototype 作用域的 Bean,Spring 只負責創建,當容器創建了 Bean 的實例後,Bean 的實例就交給客戶端代碼管理,Spring 容器將不再跟蹤其生命週期。每次客戶端請求 prototype 作用域的 Bean 時,Spring 容器都會創建一個新的實例,並且不會管那些被配置成 prototype 作用域的 Bean 的生命週期。

瞭解 Spring 生命週期的意義就在於,可以利用 Bean 在其存活期間的指定時刻完成一些相關操作。這種時刻可能有很多,但一般情況下,會在 Bean 被初始化後和被銷燬前執行一些相關操作。

在 Spring 中,Bean 的生命週期是一個很複雜的執行過程,我們可以利用 Spring 提供的方法定製 Bean 的創建過程。

當一個 Bean 被加載到 Spring 容器時,它就具有了生命,而 Spring 容器在保證一個 Bean 能夠使用之前,會進行很多工作。Spring 容器中 Bean 的生命週期流程如圖所示。

在這裏插入圖片描述
Bean 生命週期的整個執行過程描述如下。

1)根據配置情況調用 Bean 構造方法或工廠方法實例化 Bean。

2)利用依賴注入完成 Bean 中所有屬性值的配置注入。

3)如果 Bean 實現了 BeanNameAware 接口,則 Spring 調用 Bean 的 setBeanName() 方法傳入當前 Bean 的 id 值。

4)如果 Bean 實現了 BeanFactoryAware 接口,則 Spring 調用setBeanFactory() 方法傳入當前工廠實例的引用。

5)如果 Bean 實現了 ApplicationContextAware 接口,則 Spring 調用 setApplicationContext()方法傳入當前 ApplicationContext 實例的引用。

6)如果 BeanPostProcessorBean關聯,則 Spring 將調用該接口的預初始化方法postProcessBeforeInitialzation() 對 Bean 進行加工操作,此處非常重要,Spring 的AOP就是利用它實現的。

7)如果 Bean 實現了 InitializingBean 接口,則 Spring 將調用afterPropertiesSet()方法。

8)如果在配置文件中通過init-method屬性指定了初始化方法,則調用該初始化方法。

9)如果BeanPostProcessorBean關聯,則 Spring 將調用該接口的初始化方法postProcessAfterInitialization()。此時,Bean 已經可以被應用系統使用了。

10)如果在<bean>中指定了該 Bean 的作用範圍爲scope="singleton",則將該 Bean 放入 Spring IoC 的緩存池中,將觸發 Spring 對該 Bean 的生命週期管理;如果在<bean>中指定了該Bean的作用範圍爲 scope="prototype",則將該 Bean 交給調用者,調用者管理該 Bean 的生命週期,Spring 不再管理該 Bean。

11)如果 Bean 實現了DisposableBean接口,則 Spring 會調用 destory()方法將 Spring 中的 Bean 銷燬;如果在配置文件中通過 destory-method屬性指定了 Bean 的銷燬方法,則 Spring 將調用該方法對 Bean 進行銷燬。

Spring 爲 Bean 提供了細緻全面的生命週期過程,通過實現特定的接口或 <bean>的屬性設置,都可以對 Bean 的生命週期過程產生影響。雖然可以隨意配置<bean>的屬性,但是建議不要過多地使用 Bean 實現接口,因爲這樣會導致代碼和 Spring 的聚合過於緊密。

如果讀者在學習這篇文章的時候有問題可留言或私信,我都會第一時間爲你解答。

編寫不易,覺得寫的還行的話留個贊再走吧在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章