J2EE之巔

           

          自己實現IoC,AOP容器

           

          Mini-Container 開發者手冊

          (Mini-Container Beta 0.9,
          下載地址:http://www.aygfsteel.com/Files/chaocai/mini-container-beta-0.9.rar
          )

          蔡超

          軟件架構師

          軟件架構咨詢顧問

          Chaocai2001@yahoo.com.cn


          Mini-Container是本人實現的一個輕量級的IoCInversion of Control, 控制反制)容器,并且提供了對AOP的簡單支持。

          IoC容器目前已經在各種項目中的得到了廣泛的應用,它的使用大大提升了應用的可維護性和可測試性,并且簡化的了應用的構建。在作者所參與的項目中這樣的容器也無處不在。

          為了加深對這些容器原理的理解,本人開發了這個容器,在開發過程中的確在很多方面都有了新的認識,如果不是親自做過很多思想是很難體會的。

          特將此容器的實現貢獻給大家研究和學習,一同進步,一同分享,為振興中國的軟件業一同努力。

          為在”5.12 特大地震中的受難同胞祈福,愿祖國更強大!


          目錄

          Mini-Container特性

          核心技術

          從一個簡單的示例開始

          基本操作

          組件(Component)及服務(Service

          組件間的依賴

          屬性值的注入

          簡單AOP

          整合Spring


           

          Mini-Container特性

          Mini-Container是一個輕量級的IoCInversion of Control, 控制反制)容器,并且提供了對AOP的簡單支持。

          Mini-Contaiiner具有以下特性:

          1 輕量級的IoC容器,Mini-Container目前的版本使用和部署都十分簡單,僅一個jar文件,mini-container.jar,

          2 簡單AOP支持,可以對組件提供的服務方法進行攔截, 加入自定義攔截器。

          3 SOA in JVM,將SOA的思想融入其中,每個組件(component)聲名自己可以提供的服務(service),這種服務通過Java interface進行定義及描述。各組件同時聲明運行時所需依賴的服務(reference),容器會根據配置自動為該組件連接所需服務的提供者。

          4 支持與其他Framework的整合,目前mini-container可以與spring進行整合。

          運行環境要求JDK1.5以上。

          核心技術

          從一個簡單的示例開始

          以下示例展示了一個計算器服務的實現。


          Mini-container的組件配置文件:calculator.xml

          <?xml version="1.0" encoding="UTF-8"?>

          <composite xmlns="http://www.ccsoft.org/schema/components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                     xsi:schemaLocation="http://www.ccsoft.org/schema/components mini-container.xsd">

              <component name="CalculatorService" class="org.ccsoft.minicontainer.samples.calculator.impl.CalculatorServiceImpl">

                 <service interface="org.ccsoft.minicontainer.samples.calculator.CalculatorService"/>

                 <reference interface="org.ccsoft.minicontainer.samples.calculator.AddService" bind-property="addService"/>

                 <reference interface="org.ccsoft.minicontainer.samples.calculator.SubtractService" bind-property="subtractService"/> 

                 <reference interface="org.ccsoft.minicontainer.samples.calculator.MultiplyService" bind-property="multiplyService" />

                 <reference interface="org.ccsoft.minicontainer.samples.calculator.DivideService" bind-property="divideService" />  

              </component>

              <component name="AddService" class="org.ccsoft.minicontainer.samples.calculator.impl.AddServiceImpl">

                 <service interface="org.ccsoft.minicontainer.samples.calculator.AddService"/>      

              </component>

              <component name="SubtractService" class="org.ccsoft.minicontainer.samples.calculator.impl.SubtractServiceImpl">

                  <service interface="org.ccsoft.minicontainer.samples.calculator.SubtractService"/>    

              </component>

              <component name="MultiplyService" class="org.ccsoft.minicontainer.samples.calculator.impl.MultiplyServiceImpl">

                 <service interface="org.ccsoft.minicontainer.samples.calculator.MultiplyService"/>    

              </component>

              <component name="DivideService" class="org.ccsoft.minicontainer.samples.calculator.impl.DivideServiceImpl">

                 <service interface="org.ccsoft.minicontainer.samples.calculator.DivideService"/>   

              </component>

          </composite>

          可見配置文件,清晰的表達了這種組件與服務間的關系,實現代碼參見CalculatorSample

          基本操作

          1 初始化一個Mini-Container

          MiniContainer container=new MiniContainer();

                        container.loadBundlesFromClassPath("first.xml");

          2 獲取可用組件

          //獲取服務上下文

          ServiceContext context=container.getServiceContext();            

          SaySomething service=(SaySomething) container.getServiceContext().getServiceByType(SaySomething.class.getName());

          獲取組件可以根據組件提供的服務及組件名來獲取。

          其它相關API

                 /**

                  * get the service instance by component name

                  * @param name component name

                  * @return

                  */

                 public Object getServiceByName(String name);

                 /**

                  * get the service instance by service type

                  * @param type service type

                  * @return

                  */

                 public Object getServiceByType(String type);

                 /**

                  * get the service instance by service type and component name

                  * @param type service type

                  * @param name component name

                  * @return

                  */

                 public Object getServiceByType(String type,String name);

                 /**

                  * get the all the service instance by service type

                  * @param type serviceType

                  * @return

                  */

          3 獲取未激活的組件

          如果組件的依賴關系無法得到解決,則組件將處于未激活狀態,未激活的組件可以通過以下方式獲?。?/span>

          Set<?> bundles=context.getUnResolvingServiceBundles();

          組件(Component)及服務(Service

          Mini-Container中所指的組件是通過普通的Java Bean實現的,通常情況組件會通過Java Interface定義組件所能提供的服務,并且通過Java Bean(組件的實現來實現這個接口)。

          配置文件定義如下:

          <?xml version="1.0" encoding="UTF-8"?>

          <composite xmlns="http://www.ccsoft.org/schema/components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                     xsi:schemaLocation="http://www.ccsoft.org/schema/components mini-container.xsd">

              <component name="AddService" class="org.ccsoft.minicontainer.samples.calculator.impl.AddServiceImpl">

                 <service interface="org.ccsoft.minicontainer.samples.calculator.AddService"/>      

              </component>

          </composite>

          接口:AddService.java

          package org.ccsoft.minicontainer.samples.calculator;

          /**

           * The Add service interface

           */

          public interface AddService {

              double add(double n1, double n2);

          }

          組件實現:AddServiceImpl.java

          package org.ccsoft.minicontainer.samples.calculator.impl;

          import org.ccsoft.minicontainer.samples.calculator.AddService;

          /**

           * An implementation of the Add service

           */

          public class AddServiceImpl implements AddService {

              public double add(double n1, double n2) {

                  return n1 + n2;

              }

          }

          一個組件可以實現多個接口,從而暴露多個服務。

          組件間的依賴

          Mini-Container能夠通過IoC幫助我們管理組件間的依賴。與Spring不同的是我們通常不需指明具體依賴的組件的名字,而是指明所依賴的服務(即java interface)。

          <component name="CalculatorService" class="org.ccsoft.minicontainer.samples.calculator.impl.CalculatorServiceImpl">

                 <service interface="org.ccsoft.minicontainer.samples.calculator.CalculatorService"/>

                 <reference interface="org.ccsoft.minicontainer.samples.calculator.AddService" bind-property="addService"/>

                 <reference interface="org.ccsoft.minicontainer.samples.calculator.SubtractService" bind-property="subtractService"/> 

                 <reference interface="org.ccsoft.minicontainer.samples.calculator.MultiplyService" bind-property="multiplyService" />

                 <reference interface="org.ccsoft.minicontainer.samples.calculator.DivideService" bind-property="divideService" />  

              </component>

          通過referece元素指定組件所依賴的服務,及這種服務實現被注入后所綁定的屬性名稱(通過bind-property指定)。

          當如果多個組件提供了某組件所依賴的服務時,容器會在其中自動選擇一個進行關系注入。通過filter屬性我們還可以在這種情況下指定具體的組件,filter屬性值為所指定的組件名。

          <reference interface="org.ccsoft.mc.samples.HelloService" bind-property="helloService" filter="sorryService"/>

          Cardinality屬性

          通過將該屬性設置為”1..n”,我們可以將多個服務提供者注入到依賴當中,但這是綁定的屬性必須是集合類型。

          <component name="helloServiceInvoker" class="org.ccsoft.mc.samples.HelloServiceInvoker">

                 <service interface="org.ccsoft.mc.samples.HelloService"/>

                 <reference interface="org.ccsoft.mc.samples.HelloService" bind-property="services" cardinality="1..n"/>

              </component>

          package org.ccsoft.mc.samples;

          import java.util.Collection;

          public class HelloServiceInvoker implements HelloService{

                 private Collection<HelloService> services;

                 public String sayHello(String sb) {

                        String ret="";

                        for (HelloService service:services){

                               ret+=service.sayHello(sb)+""n";

                        }

                        return ret;

                 }

                 public Collection<HelloService> getServices() {

                        return services;

                 }

                 public void setServices(Collection<HelloService> services) {

                        this.services = services;

                 }

          }

          屬性值的注入

          Mini-Container支持對組件實現類的特定屬性通過配置文件進行值的注入,目前版本支持注入的類型包括,數據類型,字符類型及日期類型。

          <component name="helloService" class="org.ccsoft.mc.samples.HelloServiceImpl">

                 <service interface="org.ccsoft.mc.samples.HelloService"/>  

                 <property name="greeting" value="Hi"/>

                 <property name="date" value="2008-05-08 15:00:00"/>    

              </component>

          public class HelloServiceImpl implements HelloService {

                 private String greeting;

                 private Date date;

                 public String getGreeting() {

                        return greeting;

                 }

                 public void setGreeting(String greeting) {

                        this.greeting = greeting;

                 }

                 public String sayHello(String sb) {             

                        return greeting+" "+sb+" "+date;

                 }

                 public Date getDate() {

                        return date;

                 }

                 public void setDate(Date date) {

                        this.date = date;

                 }

          }

          注意目前日期支持的格式為:yyyy-MM-dd HH:mm:ss

          簡單AOP

          Mini-Container支持了簡單的AOP功能,可以對服務的調用進行攔截。這種攔截是通過實現和定義interceptor來實現的(與EJB3interceptor幾乎一致)。

          package org.ccsoft.mc.samples;

          import org.ccsoft.mc.core.Interceptor;

          import org.ccsoft.mc.core.InvocationContext;

          public class HelloServiceInterceptor implements Interceptor {

                 public HelloServiceInterceptor() {

                        super();

                        // TODO Auto-generated constructor stub

                 }

                 public Object invoke(InvocationContext ctx) throws Exception {

                        System.out.println("before method:"+ctx.getMethod());

                        //invoke the method

                        Object ret=ctx.proceed();

                        System.out.println("after method");

                        //modify the result

                        return (String)ret+"[exist interceptor]";

                 }

          }

          配置如下

          <component name="helloService" class="org.ccsoft.mc.samples.HelloServiceImpl">

                 <service interface="org.ccsoft.mc.samples.HelloService">

                   <interceptor class="org.ccsoft.mc.samples.HelloServiceInterceptor"/>         

                 </service>   

                 <property name="greeting" value="Hi"/>

                 <property name="date" value="2008-05-08 15:00:00"/>    

              </component>

          可以通過InvocationContext對象來激活被攔截的對象的方法,通過該對象還可以獲得當前被攔截的方法的方法名及傳入的參數。

          整合Spring

          Mini-container可以于Spring進行整合,從而獲得更加完善和強大的功能,可以在spring中使用Mini-Container的組件。

          配置示例:

          <?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-2.0.xsd">

           

           <bean id="springSpeaker" class="org.ccsoft.mc.samples.support.spring.SaySometingSpringBeanImpl">

              <property name="speaker" ref="miniSpeaker"/>  

           </bean>

           <bean id="miniContainerBridge" class="org.ccsoft.mc.support.spring.MiniContainerBridge">

             <property name="configFile" value="first.xml"/>

           </bean>

           <bean id="miniSpeaker" class="org.ccsoft.mc.support.spring.MiniContainerComponentFactory">

              <property name="service" value="org.ccsoft.mc.samples.SaySomething"/>

             <property name="context" ref="miniContainerBridge"/>

           </bean>

          </beans>

                      

          說明:

          1 spring的配置加入beanorg.ccsoft.mc.support.spring.MiniContainerBridge,并通過其configFile屬性指明Mini-Container的配置文件

          2通過bean: org.ccsoft.mc.support.spring.MiniContainerComponentFactory獲取Mini-Container中注冊的服務。

          Propertyservice,指明要引入的服務

          Propertycontext,引用org.ccsoft.mc.support.spring.MiniContainerBridge

          Propertyfilter,本示例中未給出,指定mini-container中組件名稱,用于過濾服務提供組件。

          下載地址:
          http://www.aygfsteel.com/Files/chaocai/mini-container-beta-0.9.rar
          在找到合適的站點后我會Open-Source.

          posted on 2008-05-26 20:21 超越巔峰 閱讀(3653) 評論(8)  編輯  收藏 所屬分類: Design Pattern 、Java EE

          評論

          # re: 自己實現IoC,AOP容器 2008-05-26 22:23 葉澍成

          還是很期待看到source  回復  更多評論   

          # re: 自己實現IoC,AOP容器 2008-05-27 01:38 Jie

          先頂下,有時間好好看看。  回復  更多評論   

          # re: 自己實現IoC,AOP容器 2008-05-27 09:54 于翔

          呵呵,有時間好好研究下這個,對理解IOC和AOP很有幫助!  回復  更多評論   

          # re: 自己實現IoC,AOP容器 2008-05-27 10:29 hejianhuacn

          跟其它IOC框架比較,功能有什么不同?還是實現方式不同?使用這個容器跟使用其它容器比,有什么好處?  回復  更多評論   

          # re: 自己實現IoC,AOP容器 2008-05-27 10:38 蔡超

          Mini-Contaiiner具有以下特性:

          1 輕量級的IoC容器,Mini-Container目前的版本使用和部署都十分簡單,僅一個jar文件,mini-container.jar,

          2 簡單AOP支持,可以對組件提供的服務方法進行攔截, 加入自定義攔截器。

          3 SOA in JVM,將SOA的思想融入其中,每個組件(component)聲名自己可以提供的服務(service),這種服務通過Java interface進行定義及描述。各組件同時聲明運行時所需依賴的服務(reference),容器會根據配置自動為該組件連接所需服務的提供者。

          4 支持與其他Framework的整合,目前mini-container可以與spring進行整合。

          Cardinality屬性

          通過將該屬性設置為”1..n”,我們可以將多個服務提供者注入到依賴當中


          爭取很快整理好源碼后,發布給大家,希望對大家有用!

            回復  更多評論   

          # re: 自己實現IoC,AOP容器 2008-05-27 15:49 origo

          是否可以共享源代碼  回復  更多評論   

          # re: 自己實現IoC,AOP容器[未登錄] 2008-06-05 10:27 sdfsd

          等待open source  回復  更多評論   

          # re: 自己實現IoC,AOP容器 2008-07-07 12:53 Dashjim

          http://www.aygfsteel.com/Files/chaocai/mini-container-beta-0.9-a.rar下不了!!!
            回復  更多評論   

          導航

          統計

          常用鏈接

          留言簿(12)

          隨筆分類(54)

          隨筆檔案(59)

          文章分類(2)

          文章檔案(1)

          相冊

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 太白县| 克拉玛依市| 应城市| 塔城市| 元氏县| 城市| 神农架林区| 子长县| 镇雄县| 凤翔县| 犍为县| 保康县| 江源县| 阳高县| 阿合奇县| 华蓥市| 涿鹿县| 大埔区| 泰州市| 亳州市| 苏尼特右旗| 土默特右旗| 芦山县| 高邑县| 抚松县| 海南省| 津南区| 新民市| 乐陵市| 香格里拉县| 大洼县| 赤城县| 东宁县| 赣州市| 梁山县| 泗水县| 伊春市| 玉龙| 汶川县| 秭归县| 乐清市|