ioc

          Posted on 2009-06-05 14:22 閱讀(200) 評論(0)  編輯  收藏

          一、IOC的概念
                  Inversion of control 控制反轉;
                  以前: 對象的協作關系A類自己來負責;
                      A do() ---> B f1()
                             ---> C f2()
                      do(){
                          new B().f1();
                          new C().f2();
                      }
                      對象A負責建立與其協作對象的關系;
                      問題:
                          1)對象協作關系的建立與業務本身的邏輯糾纏在一起;
                          2)協作關系也是不容易維護的;(B, C發生改變)

                   現在: 對象的協作關系容器來負責;
                      
                       A do() ---> IB <---B f1()
                              ---> IC <---C f2()
                       setIB(B)
                       setIC(C)
                     對象不再負責建立與協作對象的關系, 由容器來負責對象的協作關系;       
                      
                 控制: 指對象的協作關系由誰來建立;
                 反轉: 原來由對象自己調用的變成了容器調用;
                
                 好處: 代碼更好維護, 協作關系不需要考慮了;
                                                對象依賴于接口, 協作對象發生改變以后, 不需要改變;
                 控制反轉又叫依賴注入: 將對象的協作關系由容器來注入;                               
                 
          二、 基本的容器與IOC的使用
          1, spring-framework-2.0.6-with-dependencies
                MyEclipse 自帶的有jar包,但是會有一些問題;

                我們再創建自己的user庫: spring2_lib:
                需要三個地方的包:
                spring framework/dist/spring.jar
                                 lib/jakarta-commons/*.jar
                                 lib/cglib/*.jar

                新建工程springdev 右擊, myeclipse-- add spring capabilities--- add user libriay--spring2_lib

                接口: Greeter
                      package ioc1;

                      public interface Greeter {
                             public String sayHello();
                      }
                實現類: GreeterImpl
                      package ioc1;

                      public class GreeterImpl implements Greeter{
                      private String user;
                      //提供一個set方法, 可以注入
                      public void setUser(String user) {
                         this.user = user;
                      }
                     
                      public String sayHello() {
                        
                         return "你好 " +user;
                      }
                      }

                  配置文件: applicationContext.xml
                  <?xml version="1.0" encoding="UTF-8"?>
                  <beans
          xmlns=" xmlns:xsi=" xsi:schemaLocation="http://www.springframework.org/schema/beans             <bean id="greeter" class="ioc1.GreeterImpl">
                        <property name="user"><!-- 屬性名字 -->
                  <value>zhangsan</value>
                        </property>
                      </bean>
                  </beans>

                  測試類:Test
                      import org.springframework.beans.factory.BeanFactory;
                      import org.springframework.beans.factory.xml.XmlBeanFactory;
                      import org.springframework.core.io.ClassPathResource;
                      import org.springframework.core.io.Resource;
                     
                      public class Test {
                      public static void main(String[] args) {
                         //配置文件的路徑
                         Resource rs=new ClassPathResource("/ioc1/applicationContext.xml");
                         BeanFactory bf=new XmlBeanFactory(rs);
                         Greeter gt=(Greeter) bf.getBean("greeter");//配置文件中id的名字
                         System.out.println(gt.sayHello());
                        
                      }
                      }

          2, IOC的類型:
                   1) set 方式來注入:
                          <property name=””></property>
                          其中,name屬性的取值依setter方法名而定
                          對于基本類型,spring容器會自動做類型轉換,以便賦值;

                   2)構造器的方式來注入;
                          <constructor-arg index=””></ constructor-arg>
                          其中,index表示構造方法中的參數位置(第一個參數索引為0)

                   3)實現特定的接口來注入,
                          這種方式已經不采用了,因為業務對象會依賴框架的特定接口;
                          " 侵入式 "方案;

              注入的類型:
                  1)八種基本類型+String ;
                  2)對象
                  3)集合: list, set , map , properties
                  4)null

          3, Spring 容器 :
                用于實例化對象, 然后賦值或者裝配, 生命周期管理的一種類;
                容器的種類:
                      BeanFactory: 1)所有容器的父接口, 組件的生成和組裝;
                                   2)提供了基本的IOC的功能;
                                   3)一個實現: XmlBeanFactory ,
                                     需要提供一個Resource的實例給XmlFactory, Resource對象來包裝配置文件;
                                   4)getBean(String)方法,返回一個裝配好的對象;
                                   5)在默認情況下返回的對象都采用的單例模式;
                                   6)直到調用getBean方法時, 才會實例化并且裝配對象;
                                   實例化 -- 構造對象, 給屬性賦值 -- 裝配/注入 ;

                      ApplicationContext: Spring的上下文, 也是一個容器, 是BeanFactory的子接口;
                                          增強了BeanFactory, 提供了事件處理, 國際化,復雜的生命周期管理;
                                          一般情況下用ApplicationContext, 而不用BeanFactory;
                                          實現類:
                                               ClassPathXmlApplicationContext: 依據classpath查找配置文件;
                                               容器初始化的時候會預先實例化單例的對象; 可以配置, 有的采用單例有的不用; 三、set 方式注入:
          <1>. 基本類型的注入:
                注入簡單類型: 八種基本類型+String
                方式: id是bean的id號, 唯一的; class是bean類的全路徑;
                <bean id="" ,class="">     
                      <property name=""> <!--屬性名, set方法去掉set并將首字母小寫后的名字 -->     
                          <value>屬性值</value>
                      </property>     
               </bean>                
               對于基本類型, 會自動轉換數據類型; 跟序列化的意思差不多;
                用ApplicationContext 容器寫測試類:
                  ApplicationContext ctx=new ClassPathXmlApplicationContext("/ioc1/applicationContext.xml");
                  Greeter gt2=(Greeter) ctx.getBean("greeter");
                  Greeter gt3=(Greeter) ctx.getBean("greeter");
                   System.out.println(gt2.sayHello());
                  //測試單例模式;true
                  System.out.println(gt2==gt3);

          <2>. 對象類型的注入:
               1) <ref local> 要注入的對象在同一個配置文件中;
                2) <ref bean> 要注入的對象可以分散在其他的配置文件中;
                3) 將要注入的bean類的配置信息直接嵌入到bean類中;(有點象內部類)
                   不讓客戶端直接用getBean方式獲得,該對象只被注入的對象使用;

          例子1:
                  實現類:
                  public class OderServiceImpl implements OrderService{
               private SomeBean sb; //最好用接口
          }

                  ============================第一種:<ref local>=================================
          配置文件1: <ref local>
                              使用local則定義的兩個類必須出現在同一個配置文件中
                  <!-- 第一個bean -->
                  <bean id="otherBean" class="IOC.pm.set.Class.OtherBean">
                  <property name="str"><!-- 屬性名字 -->
                     <value>someinfo</value>
                  </property>
                  </bean>
                 
                  <!-- 第二個bean -->
                  <bean id="someBean" class="IOC.pm.set.Class.SomeBean">
                  <property name="ob">
                     <ref local="otherBean"/> //另外一個bean的id;
                  </property>
                  </bean>
                
                  ===========================第二種:嵌套==================================
                  或者2: 嵌到一起: 被嵌套的bean就不能夠使用getBean()來返回了;
                         使用嵌套定義的兩個類必須出現在同一個配置文件中
                   <bean id="someBean" class="IOC.pm.set.Class.SomeBean">
             <property name="ob">
                           <!--這樣的話ohterBean只能被someBean調用 -->
                     <bean id="otherBean" class="IOC.pm.set.Class.OtherBean">
                                  <property name="str1"><!-- 屬性名字 -->
                                     <value>tarena</value>
               </property>
              </bean>
             </property>
          </bean>

                  ============================第三種:<ref bean>==================================
                  或者3: <ref bean>: 功能最強大的搜索多個配置文件;
                           加一個配置文件: otherContext.xml 放someBean的配置;
                           applicationContext.xml中 <ref bean="otherBean"/>
                           測試類中: 寫成一個字符串數組;
                           ApplicationContext ctx=new ClassPathXmlApplicationContext(
                                         new String[]{"/ioc2/applicationContext.xml","/ioc2/other-config.xml.xml"});

             <3>. 集合的注入: (看老師的示例; )
                   List: 可重復的,有序
                          可以存放字符串,對象, 以及集合;
                          <property name="list">
                     <list>
                      <value>String1</value>
                      <value>String2</value>
                     </list>
                   </property>

                   Set: 不重復, 無序
                          可以存放字符串,對象, 以及集合;
                          <property name="set">
              <set>
               <value>String1</value>
               <value>String1</value>
              </set>
             </property>

                   Map:Key(只能用String), value 鍵值對;
                          <property name="map">
              <map>
               <entry key="key1"><!-- 用key來存放key的值,用value來存放value值 -->
                <value>value1</value>
               </entry>
               <entry key="key2">
                <value>value2</value>
               </entry>
              </map>
             </property>
            
                   Properties: key(String),value(String) 鍵值對
                  
                          <property name="properties">
              <props>
               <prop key="key11">value11</prop>
               <prop key="key22">value22</prop>
              </props>
             </property>
          四、構造器的方式注入:      
                        <1>. <constructor-arg>
             <value>基本類型</value>
          </constructor-arg>
                       <2>. <constructor-arg>
             <ref bean=""></ref>
          </constructor-arg>
              <bean id="someBean" class="ioc4.SomeBean">
             <constructor-arg index="1"><!--參數的順序可以改變,下標從0開始 -->
               <value>String1</value>
             </constructor-arg>
             <constructor-arg index="0">
               <value>String2</value>
             </constructor-arg>
          </bean>

          構造器注入和set方式注入比較:
                       用構造器注入:如果要注入的對象,屬性不是特別多,并且屬性值一定要被注入后才能來使用;
                       其他情況用set方式注入;
                                           
          五、IOC的特例 ;

              1, 自動裝配, 讓容器依據某種規則,自動的對組件實施裝配;
                       在bean中:
                        autowire=""
                             <1>. byName: 匹配屬性的名字與bean的id號進行匹配; 找set方法;

                                 someBean中有一個ob的屬性:
                                  <bean id="ob" class="ioc6.OtherBean">
                          <property name="str1">
                           <value>String1</value>
                          </property>
                          </bean>
                          <bean id="someBean" class="ioc6.SomeBean" autowire="byName">
                             <property name="str1">
                              <value>String1</value>
                             </property>
                          </bean>
                         
                             <2>. byType: 尋找配置文件, 匹配的屬性類型與bean一致; 找set方法;
                                           上面例子改成byType 也是正確的, 并且ob可以改為別的名字;
                                           如果在配置文件中找到符合條件的bean的個數超過一個,會報錯;

                             <3>. constructor: 匹配構造器,看構造器的參數類型和配置文件bean的類型是否一致,
                                               一致就成功,否則報錯;
                                               匹配個數超過一個,也報錯;
                                               提供一個構造器;

                             <4>. autodetect: 自動檢測, 先構造器, 再set方法(也就是可以set方法和構造方法可以同時使用);

                        自動從配置文件中尋找對應的bean的名字;
                        注意:手動裝配會覆蓋自動裝配的策略;
                       
                    問題:
                              1)自動裝配用的很少, 配置文件中,bean的關系不清晰, 易出錯;
                                 在建立原型的時候, 快速搭建, 真正開發的時候, 一般手動配置;
                              2)自動裝配和手動裝配配合在一起使用; 手動可以覆蓋自動的;
                              3)自動裝配搭配一個裝配檢查; 屬性先檢查, 出錯后就不再進行了;
                               dependency-check=""
                                      simple :只檢查基本類型屬性是否裝配成功;
                                      objects:只檢查Object類型是否裝配成功;
                                      all:全檢查;
                               既可以和自動裝配一起使用, 也可以單獨用來檢查是否裝配成功;

                    自動裝配的使用情況:
                             1,構建系統原形;
                             2,與dependency-check=""配合使用;
                             3,手動裝配會和自動裝配要配合使用;             


               2, 用工廠的方式創建對象: 靜態工廠, 實例工廠;
                    原因是: 很多對象不方便采用配置文件去裝配;
                    如: 獲得數據庫連接, 可以寫一個ConnectionFactory, getConnection方法
                    靜態工廠類, 靜態方法, getBean("connection")就可以得到連接;
                          public static Car createCar(){// 靜態工廠,靜態方法
                return new Car();
             }
                          <bean id="car" class="ioc5.CarFactory" factory-method="createCar" />
                          Car car=(Car) ctx.getBean("car");
             System.out.println(car);
                    實例工廠: 指工廠實例化后才能使用,
                          public Car createCar(){// 必須是實例方法
                return new Car();
             }
                         <bean id="carFactory" class="ioc5.CarFactory" />
                 <bean id="car" factory-bean="carFactory"   factory-method="createCar" />

              3,繼承關系:
                   <bean id="abstractBean" class="day02.ioc7.SomeBean" abstract="true">
              <property name="str1">
               <value>string1</value>
              </property>
              <property name="num">
               <value>20</value>
              </property>
             </bean>
             <!-- 繼承關系 -->
             <bean id="someBean" parent="abstractBean">
              <property name="num">
               <value>30</value>
              </property>
                   </bean>
                 
              得到的bean不想用單例時, 在bean標簽上加 Scope=singleton/prototype


              裝配中的其它情況:
              
             單例:scope=""
                  singleton,prototype
                
             初始化與銷毀: init-method,destroy-method


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          posts - 40, comments - 9, trackbacks - 0, articles - 9

          Copyright © 希

          主站蜘蛛池模板: 浮山县| 东莞市| 铜山县| 韶关市| 贡觉县| 永靖县| 定陶县| 轮台县| 江源县| 财经| 肃宁县| 灵川县| 循化| 双柏县| 平谷区| 资讯 | 焉耆| 金坛市| 岳阳县| 婺源县| 凌云县| 新龙县| 常德市| 沂南县| 通州市| 青河县| 广汉市| 泌阳县| 苏州市| 达日县| 中牟县| 视频| 平果县| 张家港市| 楚雄市| 达拉特旗| 木里| 宁安市| 江山市| 怀宁县| 井冈山市|