繼承Bean配置
-
Spring允許繼承bean的配置,被繼承的bean稱為父bean,繼承這個父bean的bean稱為子bean。通過設置
parent
來實現繼承。 - 子bean從父bean中繼承配置,包括bean的屬性配置。
- 子bean可以覆蓋從父bean繼承過來的配置。
- 父bean可以作為配置模板,也可以作為bean實例,若只想把父bean作為模板,可以設置
<bean>
的abstract
屬性為true
,這樣Spring將不會實例化這個bean。 -
并不是
<bean>
元素里的所有屬性都會被繼承,比如:autowire,abstract等。 -
可以忽略父bean的class屬性,讓子bean指定自己的類,而共享相同的屬性配置,但是此時
abstract
必須設為true
。
我們此時有兩個 address
類型的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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.spring.autowire.Address" p:city="BeiJing" p:street="WuDaoKou"></bean>
<bean id="address1" class="com.spring.autowire.Address" p:city="BeiJing" p:street="DaZhongSi"></bean>
</beans>
兩個bean之間有很多相同的屬性比如class
和city
,因此我們如果讓第二個bean
繼承第一個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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.spring.autowire.Address" p:city="BeiJing" p:street="WuDaoKou"></bean>
<bean id="address1" p:street="DaZhongSi" parent="address"></bean>
</beans>
如果想把第一個bean不被實例化,只作為其他bean的模板bean,則可以將其設置為抽象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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.spring.autowire.Address" p:city="BeiJing" p:street="WuDaoKou" abstract="true"></bean>
<bean id="address1" p:street="DaZhongSi" parent="address"></bean>
</beans>
此時要切記抽象bean不能被實例化。
依賴bean配置
- Spring允許用戶通過depend-on屬性設定bean前置依賴的bean,前置依賴的bean會在本bean實例化之前創建好。
- 如果前置依賴于多個bean,則可以通過逗號,空格等方式配置bean的名稱。
bean的作用域
使用<bean>
的scope
屬性來配置bean的作用域:
-
singleton
:默認值。在IOC容器初始化時創建bean實例,在整個容器的生命周期內只創建這一個bean,是單例的。 -
prototype
:原型的。IOC容器初始化時不創建bean的實例,而在每次請求時都創建一個新的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="car" class="com.spring.autowire.Car" scope="prototype">
<property name="brand" value="Audi"/>
<property name="price" value="300000"/>
</bean>
</beans>
使用外部屬性文件
在配置文件里配置bean時,有時需要在bean的配置里混入系統部署的細節信息(例如:文件路徑,數據源配置信息等),而這些部署細節實際上需要和bean配置相分離。
Spring提供了一個PropertyPlaceholderConfigurer
的BeanFactory
后置處理器,這個處理器允許用戶將bean配置的部分內容外移到屬性文件中,可以在bean配置文件里使用形式為${var}
的變量,PropertyPlaceholderConfigurer
從屬性文件里加載屬性,并使用這些屬性來替換變量。
Spring還允許在屬性文件中使用${propName}
以實現屬性之間的相互引用。
示例:
如果我們不使用外部屬性文件的話,在beans-properties.xml
配置DataSource
類型的一個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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"/>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///my_test_mysql"/>
</bean>
</beans>
這樣也能配置,但是就顯得不大靈活了,當我們需要更改這些數據庫屬性參數時還得進該配置文件來更改。
如果我們使用外部資源文件來進行配置,步驟如下:
我們定義一個外部的資源文件db.properties
,里面存放數據庫的屬性配置:
user=root
password=root
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///my_test_mysql
bean配置文件beans-properties.xml
,里面配置了DataSource
類型的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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--導入屬性文件-->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置bean-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
<property name="driverClass" value="${driverClass}"/>
<property name="jdbcUrl" value="${jdbcUrl}"/>
</bean>
</beans>
通過工廠方法配置bean
靜態工廠方法
調用靜態工廠方法創建bean是將對象創建的過程封裝到靜態方法中,當客戶端需要對象時,只需要簡單地調用靜態方法,而不用關心創建對象的細節。
要聲明通過靜態方法創建的bean,需要在bean的class
屬性里指定擁有該工廠的方法的類,同時在配置文件中進行配置,具體屬性如下:
-
class
屬性:指向靜態工廠方法的全類名 -
factory-method
:指向靜態工廠方法的名字 -
construtor-arg
:如果工廠方法需要傳入參數,則使用construtor-arg
來配置參數
示例:
- 創建bean類:
package com.spring.factory;
public class Car {
private String brand;
private double price;
public Car(String brand, double price) {
this.brand = brand;
this.price = price;
}
public Car() {
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
- 創建靜態工廠類:
package com.spring.factory;
import java.util.HashMap;
import java.util.Map;
/**
* 靜態工廠方法:直接調用某一個類的靜態方法就可以返回bean實例
*/
public class StaticCarFactory {
private static Map<String,Car> cars = new HashMap <String, Car>();
static {
cars.put("audi",new Car("audi",100000));
cars.put("ford",new Car("ford",200000));
}
//靜態工廠方法
public static Car getCar(String carName) {
return cars.get(carName);
}
}
在beans-factory.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,注意不是配置靜態工廠方法實例,而是配置bean實例-->
<bean id="car1" class="com.spring.factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="audi"></constructor-arg>
</bean>
</beans>
實例工廠方法
將對象的創建過程封裝到另外一個對象實例的方法里,當客戶端需要請求對象時,只需要簡單的調用該實例方法而不需要關心對象的創建細節。
要聲明通過實例工廠方法創建的bean,需要如下步驟:
-
factory-bean
:指定擁有該工廠方法的bean -
factory-method
:指向靜態工廠方法的名字 -
constructor-arg
:如果工廠方法需要傳入參數,則使用construtor-arg
來配置參數
實例:
bean類我們使用靜態工廠方法時創建的bean類,因此我們不需要創建新的bean類。
- 創建實例工廠方法類:
package com.spring.factory;
import java.util.HashMap;
import java.util.Map;
/**
* 實例工廠方法:實例工廠的方法,即先要創建工廠本身,再調用工廠的實例工廠來返回bean的實例
*
*/
public class InstanceCarFactory {
private Map<String,Car> cars = null;
public InstanceCarFactory(){
cars = new HashMap <String, Car>();
cars.put("audi",new Car("audi",1000000));
cars.put("ford",new Car("ford",2000000));
}
public Car getCar(String brand){
return cars.get(brand);
}
}
- 在
beans-factory.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,注意不是配置靜態工廠方法實例,而是配置bean實例-->
<bean id="car1" class="com.spring.factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="audi"></constructor-arg>
</bean>
<!-- 配置工廠的實例-->
<bean id="carFactory" class="com.spring.factory.InstanceCarFactory"></bean>
<!-- 通過實例工廠來配置bean-->
<bean id="car2" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="ford"></constructor-arg>
</bean>
</beans>
通過FactoryBean配置bean
通過factoryBean來配置bean的實例
class:指向FactoryBean的全類名
property:配置FactoryBean的屬性
但實際返回的實例卻是FactoryBean的getObject()返回的實例。
package com.spring.factoryBean;
import org.springframework.beans.factory.FactoryBean;
public class CarFactoryBean implements FactoryBean<Car> {
private String brand;
public void setBrand(String brand) {
this.brand = brand;
}
//返回bean的對象
@Override
public Car getObject() throws Exception {
return new Car(brand,10000);
}
//返回bean的類型
@Override
public Class < ? > getObjectType() {
return Car.class;
}
//返回是否是單實例
@Override
public boolean isSingleton() {
return false;
}
}
<?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">
<!--
通過factoryBean來配置bean的實例
class:指向FactoryBean的全類名
property:配置FactoryBean的屬性
但實際返回的實例卻是FactoryBean的getObject()返回的實例。
-->
<bean id="car" class="com.spring.factoryBean.CarFactoryBean">
<property name="brand" value="BMW"></property>
</bean>
</beans>
通過注解配置bean(一):基于注解配置bean
我們首先要先引入一個掃描組件的概念。
在classpath中掃描組件
Spring能夠從classpath
下自動掃描,偵測和實例化具有特定注解的組件,我們稱為組件掃描。
特定組件包括:
-
@Component
:基本注解,標識了一個受Spring管理的組件 -
@Respository
:標識持久層組件 -
@Service
:標識服務層(業務層)組件 -
@Controller
:標識表現層組件
對于掃描到的組件,Spring有默認的命名策略:使用非限定類名,第一個字母小寫,也可以在注解中通過value屬性值標識組件的名稱。
當在組件類上使用了特定的注解之后,還需要在Spring的配置文件中聲明<context:component-scan>
:
base-package
屬性指定一個需要掃描的基類包,Spring容器將會掃描這個基類包里及其子包中的所有類。- 當需要掃描多個包時,可以使用逗號分隔。
- 如果僅僅希望掃描特定的類而非基包下的所有類,可使用
resource-pattern
屬性過濾特定的類,示例:
<context:component-scan
base-package="com.spring.annotation"
resource-pattern="repository/*.class"></context:component-scan>
-
<context:include-filter>
子節點表示要包含的目標類,需要與context:component-scan
節點中use-default-filters
配合使用(設置為false
) -
<context:exclude-filter>
子節點表示要排除在外的目標類 -
<context:component-scan>
下可以擁有若干個<context:include-filter>
和<context:exclude-filter>
字節。 -
<context:include-filter>
和<context:exclude-filter>
子節點支持多種類型的過濾表達式,在此介紹兩種:
類別 | 示例 | 說明 |
---|---|---|
annotation | com.cerr.XxxAcnotaion | 所有標注了XXXAnnotation的類。該類型采用目標類是否標注了某個注解進行過濾 |
assinable | com.cerr.XxxService | 所有繼承或擴展XXXService的類。該類型采用目標類是否繼承或擴展某個特定類進行過濾。 |
配置示例:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 指定SpringIOC容器掃描的包 -->
<!-- 可以通過resource-pattern指定掃描的資源 -->
<!--
<context:component-scan base-package="com.spring.annotation" resource-pattern="repository/*.class"></context:component-scan>
-->
<context:component-scan base-package="com.spring.annotation" use-default-filters="false">
<!-- context:exclude-filter子節點指定排除哪些指定表達式的組件-->
<!--
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
-->
<!-- context:include-filter子節點指定包含哪些指定表達式的組件,需要與context:component-scan節點中use-default-filters配合使用-->
<!--
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
-->
<!--
<context:exclude-filter type="assignable" expression="com.spring.annotation.repository.UserRepository"/>
-->
<!--
<context:include-filter type="assignable" expression="com.spring.annotation.repository.UserRepository"/>
-->
</context:component-scan>
</beans>
通過注解配置bean(二)
如果多個bean之間有關聯,比如我們定義一個接口UserRepository
如下:
package com.spring.annotation.repository;
public interface UserRepository {
void save();
}
其有一個實現類UserRepositoryImpl
:
package com.spring.annotation.repository;
import org.springframework.stereotype.Repository;
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository{
@Override
public void save() {
System.out.println("UserRepository Save..");
}
}
有一個UserService
類有該接口類型的成員變量:
package com.spring.annotation.service;
import com.spring.annotation.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private UserRepository userRepository;
public void add(){
System.out.println("UserService add..");
userRepository.save();
}
}
然后還有一個UserController
類也有一個UserService
類型的變量。
package com.spring.annotation.controller;
import com.spring.annotation.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
private UserService userService;
public void execute(){
System.out.println("UserController execute...");
userService.add();
}
}
這三個類之間就存在了關聯關系,然后我們在beans-annotation.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.spring.annotation"></context:component-scan>
</beans>
我們在主方法中獲取UserController
的bean對象并且調用其execute():
package com.spring.annotation;
import com.spring.annotation.controller.UserController;
import com.spring.annotation.repository.UserRepository;
import com.spring.annotation.repository.UserRepositoryImpl;
import com.spring.annotation.service.UserService;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
System.out.println(userController);
userController.execute();
}
}
運行代碼會發現出現異常,因為UserController
的bean對象的方法中有使用到UserService
的bean對象,而在UserService
對象的方法中也使用到了UserRepository
接口,而此時他們都未裝配,因此就出現了異常。
對于上述的異常,我們可以使用@Autowired
進行自動裝配,即在要使用到的成員類進行注解或者注解其setter
方法也可。
<context:component-scan>
元素還會自動注冊AutowiredAnnotationBeanPostProcessor
實例,該實例可以自動裝配具有@Autowired
和@Resource
、@Inject
注解的屬性。
使用@Autowired自動裝配bean
@Autowired
注解可以自動裝配具有兼容類型的單個bean屬性:
-
構造器,普通字段(即使是非public),一切具有參數的方法都可以應用
@Autowired
注解。 -
默認情況下,所有使用
@Autowired
注解的屬性都需要被設置,當Spring找不到匹配的bean裝配屬性時,會拋出異常,即我們要在配置文件中配置它,**若某一屬性允許不被設置,可以設置@Autowired
注解的request
屬性為false
,例如@Autowired(request=false)
。
對于上面錯誤的例子,我們對其加了注解后的代碼如下:
package com.spring.annotation.controller;
import com.spring.annotation.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
//加了注解
@Autowired
private UserService userService;
public void execute(){
System.out.println("UserController execute...");
userService.add();
}
}
package com.spring.annotation.service;
import com.spring.annotation.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
//加了注解
@Autowired
private UserRepository userRepository;
public void add(){
System.out.println("UserService add..");
userRepository.save();
}
}
- 默認情況下,當IOC容器里存在多個類型兼容的bean時,通過類型的自動裝配將無法工作,此時可以在
@Qualifier
注解里提供bean的名稱,Spring允許對方法的入參標注@Qualifiter
已指定注入的bean的名稱。
例如我們此時多定義一個UserRepository
的實現類UserJdbcRepository
類
package com.spring.annotation.repository;
import org.springframework.stereotype.Repository;
@Repository
public class UserJdbcRepository implements UserRepository{
@Override
public void save() {
}
}
我們再把UserRepositoryImpl
中的@Repository("userRepository")的命名去掉,變為@Repository
。此時我們有了兩個UserRepository
接口的實現類,而此時通過@AutoWired
注解的是UserRepository
接口,因此允許代碼會出現異常。
我們此時有兩種解決方法,可以在UserRepositoryImpl
中的@Repository
中加上我們注解的userRepository
。另一種方法使用@Qualifiter
注解提供bean的名稱。
注解后的UserService
如下所示:
package com.spring.annotation.service;
import com.spring.annotation.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
@Qualifier("userRepositoryImpl")
private UserRepository userRepository;
public void add(){
System.out.println("UserService add..");
userRepository.save();
}
}
-
@Autowired
注解也可以應用在數組類型的屬性上,此時Spring將會把所有匹配的bean進行自動裝配。 -
@Autowired
注解也可以應用在集合屬性上,此時Spring讀取該集合的類型信息,然后自動裝配所有與之兼容的bean。 -
@Autowired
注解用在java.util.Map
上時,若該Map的鍵值是String,那么Spring將自動裝配與之Map值類型兼容的bean,此時bean的名稱作為鍵值。
使用@Resource或@Inject自動裝配bean
這兩者與@Autowired
注解的功能類似。
@Resource
注解要求提供一個bean名稱的屬性,若該屬性為空,則自動采用標注處的變量或方法名作為bean的名稱。
@Inject
和@Autowired
注解一樣也是按類型匹配注入的bean,但沒有required
屬性。我們建議使用@Autowired
注解。
泛型依賴注入(Spring4的新特性)
Spring 4中可以為子類注入子類對應的泛型類型的成員變量的引用。
即父類泛型類型之間建立了關聯關系,而對應的子類之間沒有建立關聯關系,Spring會為其對應的子類建立關聯關系。
我們以下圖所示的uml圖來舉例:
我們現在有兩個泛型父類BaseService<T>
和BaseRepository< T >
,BaseRepository<T>
是BaseService<T>
的成員變量,代碼如下:
package com.spring.generic.di;
import org.springframework.beans.factory.annotation.Autowired;
public class BaseService<T> {
@Autowired
protected BaseRepository<T> repository;
public void add(){
System.out.println("add");
System.out.println(repository);
}
}
package com.spring.generic.di;
public class BaseRepository< T > {
}
有一個User
類如下:
package com.spring.generic.di;
public class User {
}
上述兩個泛型基類的兩個子類UserService
和UserRepository
代碼如下(這兩個子類之間沒有建立關聯關系):
package com.spring.generic.di;
import org.springframework.stereotype.Service;
@Service
public class UserService extends BaseService<User> {
}
package com.spring.generic.di;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository extends BaseRepository<User> {
}
在配置文件beans-generic-di.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.spring.generic.di"/>
</beans>
主方法:
package com.spring.generic.di;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-generic-di.xml");
UserService userService = (UserService) ctx.getBean("userService");
userService.add();
}
}
運行后控制臺打印如下:
add
com.spring.generic.di.UserRepository@6d3af739
我們發現其子類之間也自動的建立了關聯關系,自動初始化了UserRepository
類。