自己实现IoC,AOP容器

Mini-Container 开发者手册

(Mini-Container Beta 0.9)
下载地址:
http://www.blogjava.net/Files/chaocai/mini-container-beta-0.9.rar
 
 
 
 
 
 
蔡超
软件架构师
软件架构咨询顾问
 


 
Mini-Container是本人实现的一个轻量级的IoC(Inversion of Control, 控制反制)容器,并且提供了对AOP的简单支持。
IoC容器目前已经在各种项目中的得到了广泛的应用,它的使用大大提升了应用的可维护性和可测试性,并且简化的了应用的构建。在作者所参与的项目中这样的容器也无处不在。
为了加深对这些容器原理的理解,本人开发了这个容器,在开发过程中的确在很多方面都有了新的认识,如果不是亲自做过很多思想是很难体会的。
特将此容器的实现贡献给大家研究和学习,一同进步,一同分享,为振兴中国的软件业一同努力。
 
为在”5.12 特大地震”中的受难同胞祈福,愿祖国更强大!


目录

 
Mini-Container是一个轻量级的IoC(Inversion 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 获取未激活的组件
如果组件的依赖关系无法得到解决,则组件将处于未激活状态,未激活的组件可以通过以下方式获取:
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 inter 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
Mini-Container支持了简单的AOP功能,可以对服务的调用进行拦截。这种拦截是通过实现和定义interceptor来实现的(与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对象来激活被拦截的对象的方法,通过该对象还可以获得当前被拦截的方法的方法名及传入的参数。
 
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"

你可能感兴趣的:(spring,AOP,应用服务器,bean,IOC)