开源框架Jdon架构研究

发布时间 : 星期三 文章开源框架Jdon架构研究更新完毕开始阅读

没有他们的复杂pointcut专门表达式。

//1. 指定被拦截的类是@Component(“a”)和@Component(“c”) @Interceptor(name = \public class MyInterceptor implements MethodInterceptor {

//2.需要实现 org.aopalliance.intercept.MethodInterceptor接口 //3.完成接口的Invoke方法

public Object invoke(MethodInvocation methodInvocation) throws java.lang.Throwable { … }

如果直接写@Interceptor(“myName”) 那么就表示该拦截器的拦截点pointcut是针对所有Service或POJOServices,相当于在aspectj.xml中的配置

@Interceptor中的pointcut是指被拦截的类名称,可以是多个类一起拦截。

框架内部组件机制

Jdon框架可以实现几乎所有组件可配置、可分离的管理,这主要得益于Ioc模式的实现,Jdon框可以说是一个组件(JavaBeans)管理的微容器。

在Jdon框架中,有三种性质的组件(JavaBeans):框架基础组件;AOP拦截器组件和应用服务组件。三种性质的组件都是通过配置文件实现可配置、可管理的,框架应用者替换这三种性质组件的任何一个。

框架基础组件是Jdon框架最基本的组件,是实现框架基本功能的组件,如果框架应用者对Jdon框架提供的功能不满意或有意替换,可以编写自己的基础功能组件替代,从而实现框架的可彻底分离或管理。Jdon框架功能开发基本思路是:当有新的功能加入Jdon框架时,总是让该功能组件实现可配置和可更换,以使得该功能代表的一类一系列其他功能有加入拓展的余地。

应用服务组件是框架应用者针对具体项目设计的组件,如用户管理AccountService、订单服务OrderService等都属于应用服务组件。

AOP拦截器组件主要是指一些应用相关的通用基础功能组件,如缓存组件、对象池组件等。相当于应用服务组件前的过滤器(Filter),在客户端访问应用服务组件之前,必须首先访问的组件功能。

这三种性质组件基本函括了应用系统开发大部分组件,应用服务组件是应用系统相关组件,基本和数据库实现相关,明显特征是一个DAO类;当应用服务组件比较复杂时,我们就可以从中重整Refactoring出一些通用功能,这些功能可以上升为框架基础组件,也可以抽象为AOP拦截器组件,主要取决于它们运行时和应用服务组件的关系。当然这三种性质框架组件之间可以相互引用(以构造方法参数形式),因为它们注册在同一个微

容器中。

使用Jdon框架,为应用系统开发者提炼行业框架提供了方便,框架应用者可以在Jdon框架基本功能基础上,添加很多自己行业特征的组件,从而实现了框架再生产,提高应用系统的开发效率。

在JdonFramework中,所有组件都是在配置文件中配置的,框架的组件是在container.xml和aspect.xml中配置,应用系统组件是在jdonframework.xml中配置,应用系统组件和框架内部或外部相关组件都是在应用系统启动时自动装载入J2EE应用服务器中,它们可以相互引用(以构造器参数引用,只要自己编写的普通JavaBeans属于构造器注射类型的类就可以),好似是配置在一个配置文件中一样。

因此,组件配置主要有三个配置文件:应用服务组件配置container.xml、AOP拦截器组件aspect.xml和应用服务组件配置jdonframework.xml 另外也有一套Annotation来起到和这些XML同样作用的配置。

内部原理

由于Jdon框架设计不断演进中,最新设计可见JdonFramework.ppt最新PPT文档 由于整个框架中中组件基于Ioc实现,组件类之间基本达到完全解耦。

从上图中可以看出,任何JavaBeans组件只要在XML配置文件(container.xml aspect.xml和jdonframework.xml)中配置,由容器装载机制注册到Ioc 容器中,这些组件的客户端,也就是访问者,只要和微容器(或者组件的接口)打交道,就可以实现组件访

问。

因此,本框架中每个功能块都可从框架中分解出来,单独使用它们。用户自己的任意功能块也可以加入框架中,Jdon框架成为一种完全开放、伸缩自如的基础平台。

运行原理图:

当客户端请求产生时,首先将访问目标服务参数包装在userTargetMetaDef对象中,该对象访问位于HttpSession中的动态代理实例,被动态代理将目标服务肢解成Method和方法参数Args,然后被拦截器拦截,最后达到目标服务实例,当然,有的拦截器可能就此完全拦截(堵住去路,如PoolInterceptor),目标服务实例是事先被注册到容器中的,在被访问时,缺省情况是每次访问产生一个新的目标服务实例。

Jdon容器如图是被保存在Servlet容器的ServletContext中的。

依赖注入组件包

Container包主要是负责容器管理方面的功能,基于Picocontainer实现依赖注入功能。其他包中的组件都被写入配置文件container.xml、aspect.xml和jdonframework.xml中,而container包主要负责与这些配置文件打交道,从配置文件中获得其他包的组件,向容器中注册,并启动容器。

主要一个接口是ContainerWrapper,ContainerWrapper有两个主要方法:向容器注册组件;从容器查询获得组件。

ContainerWrapper接口的缺省实现是PicoContainerWrapper和VisitorContainerWrapper两个子类,如下图:

PicoContainerWrapper使用了著名的PicoContainer实现(http://www.picocontainer.org),ContainerWrapper接口主要从其抽象出来。

访问者模式

VisitorContainerWraper是观察者模式的实现,传统观察者模式中,对于Visitor角色一般有下面多个访问不同被访问者的方法:

visitAcomponent(); visitBcomponent(); …..

由于Acomponent、Bcomponent这些类已经注册到容器,因此,通过容器可以直接直接实现不同组件的访问,只需通过下面一个方法实现:

public ComponentVisitor getComponentVisitor(){ return new ComponentOriginalVisitor(this); }

而访问者Visitor则可以节省为单一方法即可: visit(XXX xxx);

使用访问者模式的原因:主要为了实现缓存,提高一些组件运行性能,如果一些组件每次访问时,都需要new,例如Proxy.newInstance如果频繁反复运行,将是十分耗费性能的,因此,使用缓存尽量避免每次创建将提高系统的运行性能。

Visitor有两个子类实现:ComponentOriginalVisitor和HttpSessionProxyVisitor,这里又使用了装饰者模式,Decoratee 是ComponentOriginalVisitor;而Decorator是HttpSessionProxyVisitor,HttpSessionProxyVisitor是HttpSessionBindingListener,也就是说,我们使用了HttpSession作为缓存机制,HttpSession的特点是以用户为Key的缓存,符合♂的缓存机制,当然,我们以后也可以使用更好的缓存机制替换HttpSession,替换了HttpSession根本不必涉及到其他类的更好,因为这里使用模式实现了彻底的解耦。

访问者模式另外一个重要角色:Visitable,它则是那些运行结果需要缓存的组件必须继承的,注意,这里有一个重要点:不是那些组件本省生成需要缓存,而是它的运行结果需要缓存的。继承Visitable这些组件事先必须注册在容器中。

目前Visitable有两个子类:

* @see com.jdon.bussinessproxy.dyncproxy.ProxyInstanceFactoryVisitable * @see com.jdon.bussinessproxy.target.TargetServiceFactoryVisitable

前者主要是动态代理的创建,因为Proxy.newInstance频繁执行比较耗费性能,第一次创建后,将动态代理实例保存在httpSession中,当然每个Service对应一个动态代理实例。

TargetServiceFactoryVisitable主要是为了缓存那些目标服务的实例,目前这个功能没有激活,特殊情况下才推荐激活。

容器的启动

容器启动主要是将配置文件中注册的组件注册到容器中,并启动容器,这涉及到container包下Config和Builder等几个子包。

Config包主要负责从container.xml和aspect.xml读取组件;

Builder包主要负责向ContainerWrapper注册这些组件,注册过程是首先从基础组件(container.xml)开始,然后是拦截器组件(aspect.xml),最后是用户的服务组件(jdonframework.xml)。

容器的生命周期

容器启动后,容器本身实例是放置在Web容器的ServletContext中。

容器启动并不是在应用系统部署到Web容器时就立即启动,而是该应用系统被第一次访问时触发启动,这个行为是由ContainerSetupScript的startup触发的,而startup方法则是由ServletContainerFinder的findContainer触发。

当应用系统从Web容器中销毁或停止,Jdon框架容器也就此销毁,最好将你的组件中一些对象引用释放,只要继承Startable,实现stop方法即可。

容器的使用

客户端访问组件必需通过容器进行,这个过程分两步: 从Web容器中获得框架容器ContainerWrapper实例。

从ContainerWrapper容器中查询获得组件实例,有两者实例方式:单例和多例。 关于具体使用方式可见前面章节“如何获得POJO实例”等。

联系合同范文客服:xxxxx#qq.com(#替换为@)