Spring框架-IOC/DI詳細學習

一.IOC/DI概念html

  參考博客:http://www.javashuo.com/article/p-nnnjsjvx-gk.htmljava

   IOC(inversion of control, 控制反轉)是一種設計思想,而不是一種技術. IOC意味着將咱們設計好的對象交給容器控制,而不是交給對象內部控制.它指導咱們設計出鬆耦合,更優良的程序. 傳統程序都是由在類內部主動建立依賴對象來使用, 從而致使類與類之間高耦合, 難於測試; 有了IOC容器,把建立和查找依賴對象的控制權交給了容器, 由容器進行注入組合對象,因此對象和對象之間是鬆耦合, 這樣使得程序的整個體系結構很是靈活.web

   實際上,IOC能夠看作是一個大型中介, 將對象的信息登記其中,這個對象是什麼, 這個對象又須要什麼 ,由中介公司給對象分配它須要的資源, 以及將對象分配給須要它的對象.Spring在這個過程當中控制着對象的生命週期和對象間的關係, 全部類的建立和銷燬都由Spring控制, 而不是須要它們的類控制, 這就是控制反轉.spring

   DI(Dependency Injection, 依賴注入)是IOC的一個重點,它實現IOC的一種方法,或者說DI是IOC的另外一種說法 , 它負責實現IOC動態地向某個對象提供它所須要的其餘對象. 好比一我的須要一根掃把, 不是由這我的本身去作掃把, 而是由Spring將作好的掃把給他,  而這我的全程須要作的,就是喊我要一根掃把. 什麼叫作依賴, 人須要掃把, 人就對掃把有了依賴. 而DI就是根據這個依賴,將掃把分配給這我的的.session

 

二.IOC的使用app

  參考博客:http://www.javashuo.com/article/p-hksdeorr-by.html函數

    IOC實現的兩種方式: XML配置  ,  Spring註解測試

    依賴注入的兩種形式: Setter依賴注入, 構造方法依賴注入 ui

 

1.XML配置的兩種依賴注入形式:this

  (1)Setter依賴注入: 首先建立一個Book類,將其屬性設置好setter,getter方法

public class Book {
    private int id;
    private String name;
    private User user;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

而後在applicationContext.xml中添加bean, 告訴Spring二者的依賴關係,實現注入

    <bean name="book" class="pojo.Book">
        <property name="name" value="book1"></property>
        <property name="user" ref="user"></property>   <!--這裏將book依賴了user,所以在咱們獲取book時,會獲取指定的user對象 -->
    </bean>

    <bean name="user" class="pojo.User">
        <property name="name" value="user1"></property>
        <property name="age" value="12"></property>
    </bean>

 

(2)構造方法依賴注入:

咱們將BOOK類中添加了一個兩個參數的構造方法,而後在xml文件中肯定兩個參數的值,從而讓spring容器可以創造對象

public class Book {
    private int id;
    private String name;
    private User user;

    //Constructor
    public Book(String name,User user){
        this.name = name;
        this.user = user;
    }
}

xml文件中的配置爲: 指定了構造器有兩個參數, 第一個參數是String , 第二個參數指向了另外一個bean

    <bean name="book" class="pojo.Book">
        <constructor-arg type="java.lang.String">   <!-- 指定參數的類型,能夠在有多個構造器時不產生歧義 -->
            <value>Adel</value>
        </constructor-arg>
        <constructor-arg>
            <ref bean="user"></ref>
        </constructor-arg>
    </bean>

    <bean name="user" class="pojo.User">
        <property name="name" value="user1"></property>
        <property name="age" value="12"></property>
    </bean>

或者能夠這樣寫構造參數:

    <bean name="book" class="pojo.Book">
        <constructor-arg name="name" value="lala"></constructor-arg>
        <constructor-arg name="user" ref="user"></constructor-arg>
    </bean>

又或者這樣寫:

    <bean name="book" class="pojo.Book">
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

 

 (3) Scope對象做用域:  從Spring容器中獲取的對象的做用域能夠修改,默認的做用域爲單例, 具體以下

  • Singleton :  每一個Spring容器做用域中,一個bean定義 只對應一個對象實例 
  • Prototype:  一個bean定義對應多個對象實例
  • Request:    一個bean定義做用於HTTP request 生命週期, 指每一個HTTP request 從Spring獲取的對象實例不同. 僅在基於web的Spring ApplicationContext中有效.
  • Session:    一個bean定義做用域HTTP session 生命週期,
  • Global Session:      一個bean定義做用域全局的HTTP session 生命週期.
  • Application:       一個bean定義做用於整個ServletContext生命週期

其在配置中寫在bean的屬性Scope中:

    <bean name="book" class="pojo.Book" scope="singleton">
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

 

   (4)延遲初始化bean:    一般ApplicationContext默認在啓動時將全部singleton bean提早實例化. 一般提早實例化是好事,避免某些錯誤由於延遲實例化而不被提早發現. 可是若是想防止提早實例化, 好比你只須要用到book對象, 而不須要它初始化它的user對象, 就能夠用lazy-init屬性來控制

    <bean name="book" class="pojo.Book" >
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

    <bean name="user" class="pojo.User" lazy-init="true">
        <property name="name" value="user1"></property>
        <property name="age" value="12"></property>
    </bean>

 

(5)回調方法:  初始化回調函數init 

public class Book {
    private int id;
    private String name;
    private User user;

//    Constructor
    public Book(String name,User user){
        this.name = name;
        this.user = user;
    }

    public void init(){
        System.out.println("建立了一本書");
    }

    public void destroy(){
        System.out.println("銷燬了一本書");
    }
}

在xml文件中設置初始化回調函數,就會在建立時調用

    <bean name="book" class="pojo.Book" init-method="init" destroy-method="destroy" >
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

 

 

2.Spring註解:

    註解會削減一些配置的工做量, 可是代碼的耦合度會增長,  應當根據須要使用註解

(1)@Component註解:  這個註解和<bean>做用相似, 經過增長@Component()註解中的參數,指定其在Spring容器中的名稱. 若是不寫,則是默認其在Spring容器中的名稱爲類名的小寫 如User類 在Spring容器中默認名稱爲 user

@Component("user")
public class User {
    private int id;
    private int age;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

}

在配置文件中,即便沒有user這個bean , 其它bean也能夠用到

    <bean name="book" class="pojo.Book" init-method="init" destroy-method="destroy" >
        <constructor-arg index="0" value="lala"></constructor-arg>
        <constructor-arg index="1" ref="user"></constructor-arg>
    </bean>

    <!--<bean name="user" class="pojo.User" lazy-init="true">-->
        <!--<property name="name" value="user1"></property>-->
        <!--<property name="age" value="12"></property>-->
    <!--</bean>-->

 

(2)@Auotowired 註解:   在Spring中,可使用 @Autowired 註解經過setter方法構造函數字段自動裝配Bean。

 
 
經過setter方法
public class Book {
    private int id;
    private String name;
    private User user;

    public User getUser() {
        return user;
    }

    @Autowired
    public void setUser(User user) {
        this.user = user;
    }
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

}

這樣,即便在applicationContext.xml文件中沒有設置要在book中user依賴哪一個對象, Spring容器也會自動裝配

    <bean name="book" class="pojo.Book"  >
        <property name="name" value="lala"></property>
        <property name="id" value="12"></property>
    </bean>

    <bean name="user" class="pojo.User" lazy-init="true">
        <property name="name" value="user1"></property>
        <property name="age" value="12"></property>
    </bean>

 

經過構造函數:

public class Book {
    private int id;
    private String name;
    private User user;

//    Constructor
    @Autowired
    public Book(User user){
        this.user = user;
    }
}

 

經過字段:

public class Book {
    private int id;
    private String name;
    @Autowired
    private User user;
}

 

(3)@Resource註解  : 這個註解與@Autowired不一樣是, 它能夠指定裝配對象的名稱,或者類型,或者二者都指定

如book和user

@Component("u")
public class User {
    private int id;
    private int age;
    private String name;
//setter 和 getter
}
@Component("b")
public class Book {
    private int id;
    private String name;
    @Resource(name = "u")
    private User user;
//setter和getter
}
@Component("b")
public class Book {
    private int id;
    private String name;
    @Resource(name = "u",type = User.class)
    private User user;
}

或者這樣

@Component("b")
public class Book {
    private int id;
    private String name;
    @Resource(name = "u",type = User.class)
    private User user;
 
 
各類註解的解釋, 如下轉自  http://www.javashuo.com/article/p-hksdeorr-by.html

@Service用於註解業務層組件(咱們一般定義的service層就用這個)

@Controller用於註解控制層組件(如struts中的action)

@Repository用於註解數據訪問組件,即DAO組件

@Component泛指組件,當組件很差歸類的時候,咱們可使用這個註解進行註解。

裝配註解主要有:@Autowired、@Qualifier、@Resource,它們的特色是:

一、@Resource默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean纔會按照類型來裝配注入;

二、@Autowired默認是按照類型裝配注入的,若是想按照名稱來轉配注入,則須要結合@Qualifier一塊兒使用;

三、@Resource註解是由J2EE提供,而@Autowired是由spring提供,故減小系統對spring的依賴建議使用@Resource的方式;若是Maven項目是1.5的JRE則需換成更高版本的。

四、@Resource和@Autowired均可以書寫註解在字段或者該字段的setter方法之上

五、@Autowired 能夠對成員變量、方法以及構造函數進行註釋,而 @Qualifier 的註解對象是成員變量、方法入參、構造函數入參。

六、@Qualifier("XXX") 中的 XX是 Bean 的名稱,因此 @Autowired 和 @Qualifier 結合使用時,自動注入的策略就從 byType 轉變成 byName 了。

七、@Autowired 註釋進行自動注入時,Spring 容器中匹配的候選 Bean 數目必須有且僅有一個,經過屬性required能夠設置非必要。

八、@Resource裝配順序
  8.1. 若是同時指定了name和type,則從Spring上下文中找到惟一匹配的bean進行裝配,找不到則拋出異常
  8.2. 若是指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
  8.3. 若是指定了type,則從上下文中找到類型匹配的惟一bean進行裝配,找不到或者找到多個,都會拋出異常
  8.4. 若是既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;若是沒有匹配,則回退爲一個原始類型進行匹配,若是匹配則自動裝配;

 

如下轉自博客:https://blog.csdn.net/qq_22583741/article/details/79589910 

1.@Component取代<bean class="">
@Component("id") 取代 <bean id="" class="">
2.web開發,提供3個@Component註解衍生註解(功能同樣)取代
@Repository :dao層
@Service:service層
@Controller:web層
3.依賴注入,給私有字段設值,也能夠給setter方法設值

普通值:@Value(" ")引用值: 方式1:按照【類型】注入 @Autowired 方式2:按照【名稱】注入1 @Autowired @Qualifier("名稱") 方式3:按照【名稱】注入2 @Resource("名稱") 4.生命週期 初始化:@PostConstruct 銷燬:@PreDestroy 5.做用域 @Scope("prototype") 多例 註解使用前提,添加命名空間,讓spring掃描含有註解類

相關文章
相關標籤/搜索