首    页 建模架构 设计模式 培训咨询 jdon框架 论坛

上一级 首页 下一级


基本概念和配置篇

本章节讲述Jdon框架的基本配置和一些基本设计,是使用Jdon框架之前需要了解的章节,通过这些基本概念说明,可以让程序员对Jdon框架有一个大体概念上的轮廓。

本章节对于初学者不是必读,其中很多用法可在后面案例中学习,因此,本章节也可以直接跳过去,进入下一个章节阅读。

可彻底分离的组件管理

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

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

 

 

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

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

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

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

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

Jdon框架应用第一步

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

因此,组件配置主要有三个配置文件:应用服务组件配置container.xmlAOP拦截器组件aspect.xml和应用服务组件配置jdonframework.xml

 

 

初次使用Jdon框架时,需要在应用系统中指定自己定义的配置文件,分两步:

1. 定义自己的jdonframework.xml配置文件,这是必须的步骤。

目前Jdon框架中整合了Struts前台表现层技术,因此可以通过StrutsPlugin实现jdonframework.xml启动,这样做的好处,可以实现Struts多模块开发,一个Struts项目中可能有多个功能模块,每个功能模块涉及从页面表现(struts配置和tiles配置)、模型设计以及后台持久化等横向一系列组件,Jdon框架通过Plugin启动jdonframework.xml可以支持这种多模块开发方式。

Jdon框架已经提供一个Plugin缺省实现子类:com.jdon.strutsutil. InitPlugIn,你可以根据自己要求实现自己的Plugin实现子类。在struts-config.xml(或其它struts模块配置文件如struts-config-admin.xml等等)中配置Plugin实现子类:

<plug-in className="com.jdon.strutsutil.InitPlugIn">

    <set-property property="modelmapping-config" value="news.jdonframework.xml" />

</plug-in>

InitPlugIn主要实现从struts-config.xml中读取modelmapping-config的值,modelmapping-config的值是你自己定义的jdonframework应用配置文件,文件名不一定是jdonframework.xml,可以任意指定,例如news.jdonframework.xml表示jdonframework.xml在包名news下, com.jdon.app.myframework.xml表示myframework.xml在包名com.jdon.app下。

2. Jdon框架启动时将使用jdonframework.jarMETA-INF目录下缺省的container.xmlaspect.xml。如果你需要拓展Jdon框架,如自己开发了一些小零碎组件,如计算公式、报表组件等或者行业软件的一些通用功能,这些组件可能需要启动时就载入,或者希望它们实现可配置可替换,那么就将它们整合入Jdon框架中,有两种加入自己配置的方式(该步骤不是必需的):

第一.定义自己的组件配置文件和拦截器组件配置,文件名必须为mycontainer.xmlmyaspect.xml,这两个文件必须放置在系统的classpath路径中,或者必须在你自己的jar包,这个jar包可以和Jdon框架jar包一起部署。

第二.可以在应用系统的web.xml中定义,可以在web.xml中加入自己定义这两种配置:

<context-param>

<param-name>containerConfigure</param-name>

<param-value>/WEB-INF/mycontainer.xml</param-value>

<param-name>aspectConfigure</param-name>

<param-value>/WEB-INF/myaspect.xml</param-value>

</context-param>

<listener>

     <listener-class>com.jdon.container.startup.ServletContainerListener</listener-class>

</listener>

 那么你的mycontainer.xmlmyaspect.xml必须放置在Web项目的WEB-INF目录下,当然这两个文件名可以自己任意取名。

用户自己定义的配置文件中可以覆盖缺省的container.xmlaspect.xml相应的配置。只要取相同的name值就可以。

应用服务组件配置

jdonframework.xml是应用服务组件配置文件,文件名可自己自由定义,jdonframework.xml中主要是定义Model(模型)和Service(服务)两大要素。

jdonframework.xml最新定义由http://www.jdon.com/jdonframework.dtd规定。

<models>段落是定义应用系统的建模,一个应用系统有哪些详细具体的模型,可由Domain Model分析设计而来。<models>中的详细配置说明可见 数据模型增、删、改、查章节。

<services>段落是定义服务组件的配置,目前有两种主要服务组件配置:EJBPOJO

EJB服务组件配置如下:

<ejbService name="newsManager">

      <jndi name="NewsManager" />

      <ejbLocalObject class="news.ejb.NewsManagerLocal"/>

</ejbService>

每个ejbService组件有一个全局唯一的名字,如newsManager,有两个必须子定义:该EJBJNDI名称和其Localremote接口类。

POJO服务组件配置如下:

<pojoService name="userJdbcDao" class="news.container.UserJdbcDao">

       <constructor value="java:/NewsDS"/>

</pojoService>

POJO服务也必须有一个全局唯一名称,如userJdbcDao,以及它的class类定义。如果该POJO构造器有字符串变量,可在这里定义其变量的值,目前Jdon框架只支持构造器字符串变量注射。

如果该POJO服务需要引用其它服务,例如UserPrincipalImp类的构造器如下:

public UserPrincipalImp(UserDao userDao){

    this.userDao = userDao;

}  ……

UserPrincipalImp构造器需要引用UserDao子类实现,只需在jdonframework.xml中同时配置这两个服务组件即可,Jdon框架会自动配置它们之间的关系:

<pojoService name="userJdbcDao" class="news.container.UserJdbcDao">

       <constructor value="java:/NewsDS"/>

</pojoService>

<pojoService name="userPrincipal" class="news.container.UserPrincipalImp"/>

上面配置中news.container.UserJdbcDao是接口UserDao的子类实现,这样,直接通过userPrincipal这个名称可获得UserPrincipalImp的实例。

基础组件配置说明

container.xmlJdon框架基础组件配置文件,container.xml中包含的组件将由Jdon框架在启动时向微容器(PicoContainer)中注册,至于这些组件之间的依赖关系由微容器解决,称为Ioc模式。

container.xml内容主要由每行配置组成,每行格式如下:

<component name="组件名称" class="POJO类名称" />

<component name="modelHandler" class="com.jdon.model.handler.XmlModelHandler" />

代表组件com.jdon.model.handler.XmlModelHandler,其名称为modelHandler,如果需要在程序中调用XmlModelHandle实例,只需要以modelHandler为名称从微容器中获取即可。

组件配置也可以带有参数,例如下行:

   <component name="cache" class="com.jdon.controller.cache.LRUCache" >

      <constructor value="cache.xml"/>

   </component>

LRUCache的类代码如下:

public class LRUCache implements Cache {

  public LRUCache(String configFileName) {

   PropsUtil propsUtil = new PropsUtil(configFileName);

    cache = new UtilCache(propsUtil);   

  }

    ……..

}

这样LRUCache 中的configFileName值就是cache.xml,在cache.xml中定义了有关缓存的一些设置参数。目前Jdon框架只支持构造器是纯字符串型,可多个字符串变量,但不能字类型和其它类型混淆在一起作为一个构造器的构造参数。如果需要多个类型作为构造参数,可新建一个包含字符串配置的类,这个类就可和其它类型一起作为一个构造器的构造参数了。

一般在container.xml中的组件是框架基本功能的类,不涉及到具体应用系统。

拦截器组件配置说明

本篇为高级应用,初学者可以后再深入研究。

aspect.xml是关于拦截器组件配置,有两个方面:advice(拦截器Interceptor)和pointcut(切入点)两个方面配置,有关AOP的基本概念可见:http://www.jdon.com/AOPdesign/aspectJ.htm

Jdon AOP的设计目前功能比较简单,不包括标准AOP中的MixinIntroduction等功能;Pointcut不是针对每个class和方法,而是针对一组class(如POJO组或EJB组),拦截粒度最粗,与许多复杂完整的AOP框架(如AspectJSpring)不同的是:Jdon AOP在粒度方面是最粗的,AspectJ最细,Spring中等,如果你需要粒度细腻的AOP功能,还是推荐使用SpringAspectJ。目前这样设计是主要有两个原因:

每个类在运行时刻都实现动态拦截,在性能上有所损失,这如同职责链模式缺点一样。

在实际应用中,可以通过代理模式Proxy、装饰模式Decorator实现一些细腻度拦截,结合容器的Ioc特性,这两个代理模式使用起来非常方便,运行性能有一定提高。

Jdon AOP主要针对拦截器Interceptor设计,它可以为所有jdonframework.xml中定义的Service提供拦截器;所有的拦截器被放在一个拦截器链InterceptorsChain中。

Jdon AOP并没有为每个目标实例都提供拦截器配置的功能,在JdonAOP中,目标对象是以组为单位,而非每个实例,类似Cache/Pool等这些通用拦截器都是服务于所有目标对象。

JdonAOP拦截器目标对象组有三种:全部目标服务;EJB服务;POJO服务(EJB服务和POJO服务是在JdonFramework.xml中定义的ejbServicepojoService)。从而也决定了Pointcut非常简单。以下是aspect.xml中的配置:

<interceptor name="cacheInterceptor"

class="com.jdon.aop.interceptor.CacheInterceptor"

pointcut="services" />

其中pointcut有三种配置可选:services ; pojoServicesejbServices

拦截器配置也可以如组件配置一样,带有constructor参数,以便指定有关拦截器设置的配置文件名。

拦截器的加入不只是通过配置自己的aspect.xml可以加入,也可以通过程序实现,调用WebAppUtiladdInterceptor方法即可,该方法只要执行一次即可。

如何实现自己的拦截器?

本篇为高级应用,初学者可以后再深入研究。

以对象池拦截器PoolInterceptor为例,对象池是使用Aapche Commons Pool开源产品,对象池主要是为了提高POJO Service的运行性能,在没有对象池的情形下,POJO Service每次被访问时,要产生一个新的实例,如果并发访问用户量很大,JVM将会频繁创建和销毁大量对象实例,这无疑是耗费性能的。

使用对象池则可以重复使用一个先前以前生成的POJO Service实例,这也是Flyweight模式一个应用。

对象池如何加入到Jdon框架中呢?有两种方式:1.替代原来的POJO Service实例创建方式,属于PojoServiceFactory实现(SpringTargetSource实现);2.通过拦截器,拦截在原来的PojoServiceFactory实现之前发生作用,同时屏蔽了原来的PojoServiceFactory实现。Jdon框架采取的这一种方式。

首先,为拦截器准备好基础组件。 对象池拦截器有两个:对象池com.jdon.controller.pool.CommonsPoolAdapter和对象池工厂com.jdon.controller.pool.CommonsPoolFactory,这两个实现是安装Apache Pool要求实现的。

第二步,需要确定拦截器的Pointcut范围。前面已经说明,在Jdon框架中有三个Pointcut范围:所有服务、所有EJB服务和所有POJO服务,这种划分目标的粒度很粗糙,我们有时希望为一些服务群指定一个统一的拦截器,例如,我们不想为所有POJO服务提供对象池,想为指定的一些目标服务(如访问量大,且没有状态需要保存的)提供对象池,那么如何实现呢?这实际是如何自由划分我们自己的目标群(或单个目标实例)的问题

我们只要制作一个空接口Poolable,其中无任何方法,只要将我们需要对象池的目标类实现这个接口即可,例如com.jdon.security.web.AbstractUserPrincipal多继承一个接口Poolable,那么AbstractUserPrincipal所有的子类都将被赋予对象池功能,所有子类实例获得是从对象池中借入,然后自动返回。

这种通过编程而不是配置实现的Pointcut可灵活实现单个目标实例拦截或一组目标实例拦截,可由程序员自由指定划分,非常灵活,节省了琐碎的配置,至于Pointcut详细到类方法适配,可在拦截器中代码指定,如缓存com.jdon.aop.interceptor.CacheInterceptor只拦截目标服务类中的getXXXX方法,并且该方法的返回结果类型属于Model子类,为了提高性能,CacheInterceptor将符合条件的所有方法在第一次检查合格后缓存起来,这样,下次无需再次检查,省却每次检查。

第三步,确定拦截器在整个拦截器链条中的位置。这要根据不同拦截器功能决定,对象池拦截器由于是决定目标服务实例产生方式,因此,它应该最后终点,也就是在拦截器链中最后一个执行,aspect.xml中配置拦截器是有先后的:

  <interceptor name="cacheInterceptor"

class="com.jdon.aop.interceptor.CacheInterceptor" pointcut="services" />

 

  <interceptor name="poolInterceptor"

class="com.jdon.aop.interceptor.PoolInterceptor" pointcut="pojoServices" />

拦截器链中排序是根据Interceptorname值排序的,cacheInterceptor第一个字母是c,而poolInterceptor第一个字母是p,按照字母排列顺序,cacheIntercepotr排在poolInterceptor之前,在运行中cacheInterceptor首先运行,在以后增加新拦截器时,要注意将poolInterceptor排在最后一个,name值是可以任意指定的,如为了使PoolInterceptor排在最后一个,可命名为zpoolInterceptor,前面带一个z字母。

第四步,确定拦截器激活行为是在拦截点之前还是之后,或者前后兼顾,这就是advice的三种性质:BeforeAfterAround,这分别是针对具体拦截点jointcut位置而言。

虽然Jdon框架没有象Spring那样提供具体的BeforeAdviceAfterReturningAdvice等接口,其实这些都可以有程序员自己直接实现。

Jdon框架的拦截器和Spring等遵循aopallianceAOP框架继承同一个接口MethodInterceptor,也就是说,一个拦截器在这些不同AOP框架之间可以通用,具体实现方式不同而已。

例如,一个AroundAdvice实现如下代码,它们都只需要完成invoke方法内尔:

public class AroundAdvice   implements MethodInterceptor

{

   public Object invoke( MethodInvocation invocation)  throws Throwable

   {

      System.out.println("Hello world! (by " + this.getClass().getName() + ")");

      invocation.proceed();

      System.out.println("Goodbye! (by " + this.getClass().getName() + ")");

      return null;

   }

}

beforeAdvice实现代码如下:

public class BeforeAdvice   implements MethodInterceptor

{

   public Object invoke( MethodInvocation invocation)  throws Throwable

   {

      System.out.println("Hello world! (by " + this.getClass().getName() + ")");

      invocation.proceed();

   }

}

由此可以注意到,invocation.proceed()类似一个joincut点,这个方法类似400米接力比赛中的传接力棒,将接力棒传到下一个拦截器中,非常类似与servletFilter中的chain.doFilter(request, response);拦截器一些更详细说明可参考Spring相关文档,如下面网址:http://www.onjava.com/pub/a/onjava/2004/10/20/springaop2.html,和Jdon拦截器原理基本一致。

考察对象池拦截器功能,它实际是一个around advice,在joincut之前需要从对象池借用一个目标服务实例,然后需要返回对象池。com.jdon.aop.interceptor.PoolInterceptor主要核心代码如下:

Pool pool = commonsPoolFactory.getPool(); //获得对象池

Object poa = null;

Object result = null;

 try {

    poa = pool.acquirePoolable(); //借用一个服务对象

    Debug.logVerbose(" borrow a object:" + targetMetaDef.getClassName()

                    + " from pool", module);

    //set the object that borrowed from pool to MethodInvocation

    //so later other Interceptors or MethodInvocation can use it!

    proxyMethodInvocation.setThis(poa);  //放入invocation,以便供使用

    result = invocation.proceed();

} catch (Exception ex) {

    Debug.logError(ex, module);

 } finally {

    if (poa != null) {

      pool.releasePoolable(poa);  //将服务对象归还对象池

      Debug.logVerbose(" realease a object:" + targetMetaDef.getClassName()

                        + " to pool", module);

    }

 }

 return result;

经过上述四步考虑,我们基本可以在Jdon框架动态plugin自己的拦截器,关于对象池拦截器有一点需要说明的,首先EJB服务因为有EJB容器提供对象池功能,因此不需要对象池了,在POJO服务中,如果你的POJO服务设计成有状态的,或者你想让其成为单例,就不能使用对象池,只要你这个POJO服务类不继承Poolable,它的获得是通过组件实例方式获得,参考后面“组件实例和服务实例”章节。



上一级 首页 下一级


更多Jdon框架专题讨论

JdonFramework作为一个免费开源软件开发平台,可以商用开发大多数数据库应用软件和管理软件: 电子商务软件 在线教育软件 税务软件 Web快速开发软件 财务软件 购物车软件 医院帐务软件 crm software medical software 人事薪资软件payroll software 在线购物软件 销售软件 项目管理软件 房产不动产管理软件 生产软件 PDM软件 制造业软件 仓库软件 采购软件 进销存软件 危险源监控软件 物流软件 超市软件 银行软件 保险软件 汽车软件 医疗软件 电子软件 自动化软件 服装软件 烟草软件 分销管理软件 供应商管理软件

下载源码

框架文档

框架应用系统

演示运行

JiveJdon3

性能测试

Q&A 问答

技术支持

 

 

更多标签...



Jdon框架演示

JiveJdon
源码下载

VIP收费区

历史热点讨论排行榜




google yahoo 新浪ViVi 365Key网摘 天极网摘 CSDN网摘 添加到百度搜藏 POCO网摘





手机 add to google add to yahoo
联系我们 | 关于我们 | 广告联系 | 网站地图 | 设为首页

沪ICP证08026060 如有意见请与我们联系 Powered by JdonFramework
_×
您有新消息