1. 程式人生 > >Spring4深入理解IOC&DI04----Bean配置方式(全類名,工廠方法,FactoryBean),配置形式(基於XML和註解),泛型依賴注入

Spring4深入理解IOC&DI04----Bean配置方式(全類名,工廠方法,FactoryBean),配置形式(基於XML和註解),泛型依賴注入

一、Bean的配置方式

    Bean 的配置方式:通過全類名(反射)、通過工廠方法(靜態工廠方法 & 例項工廠方法)、FactoryBean

1-1.通過靜態工廠方式配置Bean

  --•呼叫靜態工廠方法建立Bean是將物件建立的過程封裝到靜態方法中.當客戶端需要物件時,只需要簡單地呼叫靜態方法,而不同關心建立物件的細節.   --•要宣告通過靜態方法建立的 Bean,需要在Beanclass屬性裡指定擁有該工廠的方法的類,同時在factory-method屬性裡指定工廠方法的名稱.最後,使用<constrctor-arg>元素為該方法傳遞方法引數. 1-2.通過例項工廠方式配置Bean

  •例項工廠方法: 將物件的建立過程封裝到另外一個物件例項的方法裡.當客戶端需要請求物件時,只需要簡單的呼叫該例項方法而不需要關心物件的建立細節.   •要宣告通過例項工廠方法建立的 Bean     –bean factory-bean屬性裡指定擁有該工廠方法的Bean     –factory-method屬性裡指定該工廠方法的名稱     –使用 construtor-arg元素為工廠方法傳遞方法引數
/**
 * InstanceCarFactory:例項工廠方法
 * 例項工廠的方法,即需要先建立工廠本身,再呼叫工廠的例項方法來返回bean的例項
 *
 * @author Lcw 2015/11/12
 */
public class InstanceCarFactory {
    private Map<String, Car> cars = null;

    public InstanceCarFactory() {
        cars = new HashMap<String, Car>();
        cars.put("audi", new Car("audi", 500000));
        cars.put("ford", new Car("ford", 600000));
    }

    public Car getCar(String brand) {
        return cars.get(brand);
    }
}
/**
 * StaticCarFactory:靜態工廠方法:直接呼叫某一個類的靜態方法就可以返回Bean例項
 */
public class StaticCarFactory {
    private static Map<String , Car> cars = new HashMap<String, Car>();

    static {
        cars.put("audi",new Car("audi", 30000));
        cars.put("ford",new Car("ford", 40000));
    }

    //靜態工廠方法: 注意:要在配置檔案XML裡配置Car而不是StaticCarFactory
    public static Car getCar(String name) {
        return cars.get(name);
    }
}
<?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 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!--通過靜態工廠方法來配置bean, 注意不是配置靜態工廠方法例項,而是配置bean例項-->
    <!--factory-method: 指向靜態工廠方法的名字
        constructor-arg:如果工廠方法需要傳入引數,則使用constructor-arg來配置引數-->
    <bean id="car1" class="Spring4_IOC.bean.factory.StaticCarFactory"
            factory-method="getCar">
        <constructor-arg value="audi"/>
    </bean>

    <!--配置例項工廠的例項-->
    <bean id="carFactory" class="Spring4_IOC.bean.factory.InstanceCarFactory"/>
    <!-- 通過例項工廠方法來配置bean-->
    <bean id="car2" factory-bean="carFactory" factory-method="getCar">
        <constructor-arg value="ford"/>
    </bean>
</beans>
    /**
     * Bean 的配置方式:-、通過全類名(反射);二、通過工廠方法(靜態工廠方法 & 例項工廠方法);三、FactoryBean
     *
     * 靜態工廠方法:直接呼叫某一個類的靜態方法就可以返回Bean例項
     * 例項工廠方法:例項工廠的方法,即需要先建立工廠本身,再呼叫工廠的例項方法來返回bean的例項
     */
    @Test
    public void testStaticFactory() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-factory.xml");
        //測試靜態工廠方法
        Car car1 = (Car) ctx.getBean("car1");
        System.out.println(car1);

        //例項工廠方法
        Car car2 = (Car) ctx.getBean("car2");
        System.out.println(car2);
    }
1-3.實現 FactoryBean 介面在 Spring IOC 容器中配置 Bean
Spring 中有兩種型別的Bean,一種是普通Bean,另一種是工廠Bean,FactoryBean.工廠 Bean 跟普通Bean不同,其返回的物件不是指定類的一個例項,其返回的是該工廠BeangetObject方法所返回的物件
/**
 * CarFactoryBean:自定義的factoryBean需要實現FactoryBean
 */
public class CarFactoryBean implements FactoryBean<Car> {
    private String brand;
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }

    public CarFactoryBean() {
    }
    //下面是三個實現方法
    //返回bean的物件
    public Car getObject() throws Exception {
        return new Car("BMW" , 500000);
    }

    //返回bean的型別Class<?>  中?表示一個未知的類
    public Class<?> getObjectType() {
        return Car.class;
    }

    public boolean isSingleton() {
        return true;
    }
}
<?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 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!--
        通過factoryBean來配置Bean的例項
        class:指向FactoryBean的全類名
        property:配置FactoryBean的屬性

        但實際返回的例項確是FactoryBean的getObject()返回的例項-->
   <bean id="car" class="Spring4_IOC.bean.CarFactoryBean">
       <property name="brand" value="BMW"/>
   </bean>
</beans>
   /**
     * Bean 的配置方式:-、通過全類名(反射);二、通過工廠方法(靜態工廠方法 & 例項工廠方法);三、FactoryBean
     *
     * 測試FactoryBean
     * Spring 中有兩種型別的 Bean, 一種是普通Bean, 另一種是工廠Bean, 即FactoryBean
     */
    @Test
    public void testFactoryBean() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-beanFactory.xml");
        Car car = (Car) ctx.getBean("car");  //注意這個在類是Car!
        System.out.println(car);
    }

二、Bean的配置形式

    配置形式:基於 XML 檔案的方式;基於註解的方式(基於註解配置 Bean;基於註解來裝配 Bean 的屬性)
在 classpath 中掃描元件
元件掃描(componentscanning): Spring能夠classpath下自動掃描,偵測和例項化具有特定註解的元件.特定元件包括:@Component: 基本註解,標識了一個受Spring管理的元件@Respository:標識持久層元件@Service: 標識服務層(業務層)元件@Controller: 標識表現層元件對於掃描到的元件,Spring有預設的命名策略:使用非限定類名,第一個字母小寫.也可以在註解中通過value屬性值標識元件的名稱當在元件類上使用了特定的註解之後,還需要在Spring的配置檔案中宣告<context:component-scan>base-package 屬性指定一個需要掃描的基類包Spring容器將會掃描這個基類包裡及其子包中的所有類.當需要掃描多個包時, 可以使用逗號分隔.如果僅希望掃描特定的類而非基包下的所有類,可使用 resource-pattern屬性過濾特定的類,示例:<context:include-filter>子節點表示要包含的目標類<context:exclude-filter>子節點表示要排除在外的目標<context:component-scan>下可以擁有若干個<context:include-filter><context:exclude-filter>子節點

以下 類那放在這個檔案下Spring4_IOC.annotation

@Component
public class TestObject {
}
respository介面跟實現類
public interface UserRepository {
    void save();
}
//介面實現一般用介面名
@Repository("userRepository")
public class UserRepositoryImpl implements UserRepository {
    public void save() {
        System.out.println("UserRepository Save...");
    }
}
Service層跟controller
@Service
public class UserService {
   //@Autowired(required=false) //如果沒有這個類,輸出為null
   @Autowired
    private UserRepository userRepository;

    public void add() {
        System.out.println("UserService add...");
        userRepository.save();
    }
}
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void execute() {
        System.out.println("UserController execute...");
        userService.add();
    }
}
<?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 http://www.springframework.org/schema/context/spring-context.xsd">

   <!--指定Spring IOC容器掃描的包-->
    <!--可以通過resource-pattern指定掃描的資源-->
    <!--<context:component-scan base-package="Spring4_IOC.annotation"
            resource-pattern="repository/*.class"></context:component-scan>-->

    <!--exclude-filter: 子節點指定排除哪些指定表示式的元件-->
    <!--include-filter:子節點指定包含哪些表示式的元件,該子節點需要use-default-filters="false"配合使用-->
    <context:component-scan base-package="Spring4_IOC.annotation" >
        <!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>-->
        <!--<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>-->

        <!--<context:exclude-filter type="assignable" expression="com.changwen.spring4.annotation.repository.UserRepository"/>-->
        <!--<context:include-filter type="assignable" expression="com.changwen.spring4.annotation.repository.UserRepository"/>-->
    </context:component-scan>
</beans>
    @Test
    public void testAnnotation() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-annotation.xml");

        TestObject to = (TestObject) ctx.getBean("testObject");
        System.out.println(to);

        //類UserController第一個字母小寫 userController
        UserController userController = (UserController) ctx.getBean("userController");
        System.out.println(userController);
        userController.execute();

        UserService userService = (UserService) ctx.getBean("userService");
        System.out.println(userService);

        UserRepository userRepository = (UserRepository) ctx.getBean("userRepository");
        System.out.println(userRepository);
    }
<context:include-filter><context:exclude-filter>節點支援多種型別的過濾表示式

2-1.元件裝配

<context:component-scan>元素還會自動註冊AutowiredAnnotationBeanPostProcessor例項,該例項可以自動裝配具有@Autowired@Resource@Inject註解的屬性. 1).使用 @Autowired自動裝配Bean
@Autowired註解自動裝配具有相容型別的單個Bean屬性構造器,普通欄位(即使是非public),一切具有引數的方法都可以應用@Authwired註解預設情況下,所有使用@Authwired註解的屬性都需要被設定.Spring找不到匹配的Bean裝配屬性時,會丟擲異常,若某一屬性允許不被設定,可以設定@Authwired註解的required屬性為false預設情況下,IOC容器裡存在多個型別相容的Bean,通過型別的自動裝配將無法工作.此時可以在@Qualifier註解裡提供Bean的名稱.Spring允許對方法的入參標註@Qualifiter已指定注入Bean的名稱@Authwired註解也可以應用在陣列型別的屬性上,此時Spring將會把所有匹配的Bean進行自動裝配.@Authwired註解也可以應用在集合屬性,此時Spring讀取該集合的型別資訊,然後自動裝配所有與之相容的Bean.@Authwired註解用java.util.Map上時,若該Map的鍵值為String,那麼Spring將自動裝配與之Map值型別相容的Bean,此時Bean的名稱作為鍵值
2).使用 @Resource@Inject自動裝配Bean

Spring 還支援 @Resource@Inject註解,這兩個註解和@Autowired註解的功用類似@Resource 註解要求提供一個Bean名稱的屬性,若該屬性為空,則自動採用標註處的變數或方法名作為Bean的名稱@Inject @Autowired註解一樣也是按型別匹配注入的Bean,但沒有reqired屬性建議使用 @Autowired註解

三、泛型依賴注入

Spring 4.x 中可以為子類注入子類對應的泛型型別的成員變數的引用


public class BaseRepository<T> {
}
public class BaseService<T> {
    @Autowired
    protected BaseRepository<T> repository;

    public void add() {
        System.out.println("add...");
        System.out.println(repository);
    }
}
@Service
public class UserService extends BaseService<User> {
}
public class User {
    private String userName;
    private List<Car> cars;
    private String wifeName;

    public String getWifeName() {
        return wifeName;
    }

    public void setWifeName(String wifeName) {
        System.out.println("setWifhName: " + wifeName);
        this.wifeName = wifeName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

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

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

    public User() {
        System.out.println("User's Construtor...");
    }

    @Override
    public String toString() {
        return "User [userName=" + userName + ", cars=" + cars + "]";
    }

    public void init(){
        System.out.println("init method...");
    }

    public void destroy(){
        System.out.println("destroy method...");
    }

}
@Repository
public class UserRepository extends BaseRepository<User>{
}
配置檔案
<?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 http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  <context:component-scan base-package="Spring4_IOC.di">

  </context:component-scan>
</beans>
    /**
     * Spring 4.x 新特性:泛型依賴注入
     */
    @Test
    public void testDI() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_IOC/beans-generic.xml");
        Spring4_IOC.di.UserService userService = (Spring4_IOC.di.UserService) ctx.getBean("userService");
        System.out.println(userService);
        userService.add();
    }
[email protected]
add...
[email protected]
整合多個配置檔案
Spring 允許通過 <import>將多個配置檔案引入到一個檔案中,進行配置檔案的整合。這樣在啟動Spring容器時,僅需要指定這個合併好的配置檔案就可以。import元素的resource屬性支援Spring的標準的路徑資源


相關推薦

Spring4深入理解IOC&DI04----Bean配置方式工廠方法FactoryBean配置形式(基於XML註解)依賴注入

一、Bean的配置方式     Bean 的配置方式:通過全類名(反射)、通過工廠方法(靜態工廠方法 & 例項工廠方法)、FactoryBean 1-1.通過靜態工廠方式配置Bean   --•呼叫靜態工廠方法建立Bean是將物件建立的過程封裝到靜態方法中.當客

Spring4新特性依賴注入

什麼叫做泛型依賴注入呢? 就是帶泛型的兩個父類他們之間有引用關係, 子類各自繼承他們,子類之間彼此之間也會有父類間的引用關係。 舉例: 兩個父類:之間有引用關係。 package one;

Spring-13:依賴注入Spring4.X新特性

Spring 4.x 中可以為子類注入子類對應的泛型型別的成員變數的引用。 首先建立兩個泛型基類: BaseRepository<T> 和 BaseService<T>   public class BaseRepository<T> {

淺談spring4依賴注入

Spring 4.0版本中更新了很多新功能,其中比較重要的一個就是對帶泛型的Bean進行依賴注入的支援。Spring4的這個改動使得程式碼可以利用泛型進行進一步的精簡優化。 1. 泛型依賴注入的優點 泛型依賴注入就是允許我們在使用spring進行依賴注入的同時,利用泛型的

Spring:依賴注入註解方式依賴注入

註解方式實現依賴注入支援手工裝配和自動裝配(慎用) 一般是宣告bean和bean直接的依賴關係的時候用比較好 使用註解方式時,也支援給Field注入值(在XML中不可以給Field注入)。另外就是setter方式注入。 @Resource註解在spring安裝目錄的lib\

Spring4深入理解----事務宣告式事務xml配置事務事務傳播屬性事務其他屬性(隔離級別&回滾&只讀&過期)

  •事務管理是企業級應用程式開發中必不可少的技術,  用來確保資料的完整性和一致性.   •事務就是一系列的動作,它們被當做一個單獨的工作單元.這些動作要麼全部完成,要麼全部不起作用   •事務的四個關鍵屬性(ACID)     –原子性(atomicity):事務是一

深入理解IOC模式及Unity框架

理解 rain 框架 播放器 url 播放 builder 說明 title 深入理解IOC模式及Unity框架 研究了下,有幾篇博客確實已經說得很清楚了 1、IoC模式:http://www.cnblogs.com/qqlin/archive/

3. Spring: 深入理解IoC

3. Spring: 深入理解IoC IoC 是 Spring容器的核心,AOP、宣告式事務等功能都依賴於此功能 解耦過程例項 問題場景 解耦過程 IoC解耦 介面具體實現類的控制權從呼叫類

深入理解IOC

1. IoC理論的背景   我們都知道,在採用面向物件方法設計的軟體系統中,它的底層實現都是由N個物件組成的,所有的物件通過彼此的合作,最終實現系統的業務邏輯。 圖1:軟體系統中耦合的物件   如果我們開啟機械式手錶的後蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針

深入理解字串的底層儲存方式

引言 以下討論的,包括圖示,都是基於JDK1.8以上。因為JDK1.7的常量池在方法區,而不是在Java堆中 先了解字串常量在記憶體的表示方式,接著瞭解字串物件在記憶體的表示方式。在瞭解兩種字串表現方式後,String.intern()就將會很容易理解。 關

深入理解Spring的兩大特徵IOCAOP

眾所周知,Spring的核心特性就是IOC和AOP,IOC(Inversion of Control),即“控制反轉”;AOP(Aspect-OrientedProgramming),即“面向切面程式設計”。參考書《Spring In Action》,下面分享一

springboot的5種讀取配置方式1:直接讀取bean

1.直接讀取bean:/** * 學生實體類 * Created by ASUS on 2018/5/4 */ public class Student { private String

深入理解Nginx》閱讀與實踐:Nginx安裝配置與HelloWorld

#include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static char* ngx_http_mytest(ngx_conf_t *cf,ngx_command_t *cmd,

JAVAWEB開發之Spring詳解之——Spring的入門以及IOC容器裝配Bean(xml註解方式)、Spring整合web開發、整合Junit4測試

public class BeanFactory{    public UserService getUserService(){         // 反射+配置檔案        return Class.forName(類名).newInStance();     } } xml、pro

深入理解IOC控制反轉及應用例項

一、IOC雛形 1、程式V1.0 話說,多年以前UT公司提出一個需求,要提供一個系統,其中有個功能可以在新春佳節之際給公司員工傳送一封郵件。郵件中給大家以新春祝福,並告知發放一定數額的過節費。      經分析,決定由張三、李四和王五來負責此係統的開發。    其中:由張三

laravel 服務容器例項——深入理解IoC模式

剛剛接觸laravel,對於laravel的服務容器不是很理解。看了《Laravel框架關鍵技術解析》和網上的一些資料後對於服務容器有了一些自己的理解,在這裡分享給大家 1、依賴 IoC模式主要是用來解決系統元件之間相互依賴關係的一種模式。那麼什麼是依賴呢?下面給出依賴的例

深入理解Activity啟動流程(二)–Activity啟動相關

b- ive ava ani affinity server 組織 詳細 pac 本文原創作者:Cloud Chou. 歡迎轉載,請註明出處和本文鏈接 本系列博客將詳細闡述Activity的啟動流程,這些博客基於Cm 10.1源碼研究。 在介紹Activity的詳細啟動流程

深入理解Java虛擬機- 學習筆記 - 虛擬機加載機制

支持 pub eth 獲取 事件 必須 string 沒有 字節碼 虛擬機把描述類的數據從Class文件加載道內存,並對數據進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制。在Java裏,類型的加載、連接和初始化過程都是在程序

SpringMVC基於代碼的配置方式配置無web.xml

-c size ons imp .net rri import 右鍵 無需 基於配置文件的web項目維護起來可能會更方便,可是有時候我們會有一些特殊的需求,比方防止客戶胡亂更改配置,這時候我們須要給配置隱藏到代碼中。 1.創建一個動態web項目(無需w

深入理解JAVA虛擬機閱讀筆記——虛擬機加載機制

info 程序 動態 alt 訪問 什麽 hand jdk 靜態方法   虛擬機把描述類的Class文件加載到內存,並對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制。 在Java語言中,類型的加載、連接