Mini-Container 開發(fā)者手冊(cè)
(Mini-Container Beta 0.9,
下載地址:http://www.tkk7.com/Files/chaocai/mini-container-beta-0.9.rar
)
蔡超
軟件架構(gòu)師
軟件架構(gòu)咨詢顧問
Chaocai2001@yahoo.com.cn
序
Mini-Container是本人實(shí)現(xiàn)的一個(gè)輕量級(jí)的IoC(Inversion of Control, 控制反制)容器,并且提供了對(duì)AOP的簡單支持。
IoC容器目前已經(jīng)在各種項(xiàng)目中的得到了廣泛的應(yīng)用,它的使用大大提升了應(yīng)用的可維護(hù)性和可測(cè)試性,并且簡化的了應(yīng)用的構(gòu)建。在作者所參與的項(xiàng)目中這樣的容器也無處不在。
為了加深對(duì)這些容器原理的理解,本人開發(fā)了這個(gè)容器,在開發(fā)過程中的確在很多方面都有了新的認(rèn)識(shí),如果不是親自做過很多思想是很難體會(huì)的。
特將此容器的實(shí)現(xiàn)貢獻(xiàn)給大家研究和學(xué)習(xí),一同進(jìn)步,一同分享,為振興中國的軟件業(yè)一同努力。
為在”5.12 特大地震”中的受難同胞祈福,愿祖國更強(qiáng)大!
目錄
序
Mini-Container特性
核心技術(shù)
從一個(gè)簡單的示例開始
基本操作
組件(Component)及服務(wù)(Service)
組件間的依賴
屬性值的注入
簡單AOP
整合Spring
Mini-Container特性
Mini-Container是一個(gè)輕量級(jí)的IoC(Inversion of Control, 控制反制)容器,并且提供了對(duì)AOP的簡單支持。
Mini-Contaiiner具有以下特性:
1 輕量級(jí)的IoC容器,Mini-Container目前的版本使用和部署都十分簡單,僅一個(gè)jar文件,mini-container.jar,
2 簡單AOP支持,可以對(duì)組件提供的服務(wù)方法進(jìn)行攔截, 加入自定義攔截器。
3 SOA in JVM,將SOA的思想融入其中,每個(gè)組件(component)聲名自己可以提供的服務(wù)(service),這種服務(wù)通過Java interface進(jìn)行定義及描述。各組件同時(shí)聲明運(yùn)行時(shí)所需依賴的服務(wù)(reference),容器會(huì)根據(jù)配置自動(dòng)為該組件連接所需服務(wù)的提供者。
4 支持與其他Framework的整合,目前mini-container可以與spring進(jìn)行整合。
運(yùn)行環(huán)境要求:JDK1.5以上。
核心技術(shù)
從一個(gè)簡單的示例開始
以下示例展示了一個(gè)計(jì)算器服務(wù)的實(shí)現(xiàn)。

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>
可見配置文件,清晰的表達(dá)了這種組件與服務(wù)間的關(guān)系,實(shí)現(xiàn)代碼參見CalculatorSample。
基本操作
1 初始化一個(gè)Mini-Container
MiniContainer container=new MiniContainer();
container.loadBundlesFromClassPath("first.xml");
2 獲取可用組件
//獲取服務(wù)上下文
ServiceContext context=container.getServiceContext();
SaySomething service=(SaySomething) container.getServiceContext().getServiceByType(SaySomething.class.getName());
獲取組件可以根據(jù)組件提供的服務(wù)及組件名來獲取。
其它相關(guān)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 獲取未激活的組件
如果組件的依賴關(guān)系無法得到解決,則組件將處于未激活狀態(tài),未激活的組件可以通過以下方式獲取:
Set<?> bundles=context.getUnResolvingServiceBundles();
組件(Component)及服務(wù)(Service)
Mini-Container中所指的組件是通過普通的Java Bean實(shí)現(xiàn)的,通常情況組件會(huì)通過Java Interface定義組件所能提供的服務(wù),并且通過Java Bean(組件的實(shí)現(xiàn)來實(shí)現(xiàn)這個(gè)接口)。
配置文件定義如下:
<?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);
}
組件實(shí)現(xiàn):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;
}
}
一個(gè)組件可以實(shí)現(xiàn)多個(gè)接口,從而暴露多個(gè)服務(wù)。
組件間的依賴
Mini-Container能夠通過IoC幫助我們管理組件間的依賴。與Spring不同的是我們通常不需指明具體依賴的組件的名字,而是指明所依賴的服務(wù)(即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元素指定組件所依賴的服務(wù),及這種服務(wù)實(shí)現(xiàn)被注入后所綁定的屬性名稱(通過bind-property指定)。
當(dāng)如果多個(gè)組件提供了某組件所依賴的服務(wù)時(shí),容器會(huì)在其中自動(dòng)選擇一個(gè)進(jìn)行關(guān)系注入。通過filter屬性我們還可以在這種情況下指定具體的組件,filter屬性值為所指定的組件名。
<reference interface="org.ccsoft.mc.samples.HelloService" bind-property="helloService" filter="sorryService"/>
Cardinality屬性
通過將該屬性設(shè)置為”1..n”,我們可以將多個(gè)服務(wù)提供者注入到依賴當(dāng)中,但這是綁定的屬性必須是集合類型。
<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支持對(duì)組件實(shí)現(xiàn)類的特定屬性通過配置文件進(jìn)行值的注入,目前版本支持注入的類型包括,數(shù)據(jù)類型,字符類型及日期類型。
<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功能,可以對(duì)服務(wù)的調(diào)用進(jìn)行攔截。這種攔截是通過實(shí)現(xiàn)和定義interceptor來實(shí)現(xiàn)的(與EJB3的interceptor幾乎一致)。
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對(duì)象來激活被攔截的對(duì)象的方法,通過該對(duì)象還可以獲得當(dāng)前被攔截的方法的方法名及傳入的參數(shù)。
整合Spring
Mini-container可以于Spring進(jìn)行整合,從而獲得更加完善和強(qiáng)大的功能,可以在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的配置加入bean:org.ccsoft.mc.support.spring.MiniContainerBridge,并通過其configFile屬性指明Mini-Container的配置文件
2通過bean: org.ccsoft.mc.support.spring.MiniContainerComponentFactory獲取Mini-Container中注冊(cè)的服務(wù)。
Property:service,指明要引入的服務(wù)
Property:context,引用org.ccsoft.mc.support.spring.MiniContainerBridge
Property:filter,本示例中未給出,指定mini-container中組件名稱,用于過濾服務(wù)提供組件。
下載地址:
http://www.tkk7.com/Files/chaocai/mini-container-beta-0.9.rar
在找到合適的站點(diǎn)后我會(huì)Open-Source.