直挂云帆济沧海,展翅遨翔登九天!

我要飞得更高...

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  19 随笔 :: 0 文章 :: 5 评论 :: 0 Trackbacks

2008年3月30日 #

        从这一阶段开始讲述软件设计模式,我也不再讲GoF的神奇历史,直接进入正题。在进行模式讲解的同时,对于本人来说,一方面也是进行了复习,另一方面也是通过讲解使自己对这些模式的使用上达到一个更加理解的层次。搞软件的朋友都知道,在进行开发过一段时间后,会发现自己大学里学习的基础课很重要。而目前很多朋友对软件的理解都非常肤浅,只知道增删改查,试用这样的程序员能存活多久,思考很重要,学习很重要,理解很重要,领悟更重要。让浮燥的程序员回归理性吧,模式可能让浮燥的心情得到净化,在模式中进行思考,在模式中进行领悟吧。
        第一讲是装饰器。当初我在学装饰器模式的时候总是感觉似懂非懂,一直没有真正理解。其实装饰器也叫油漆工模式,再加上在我们的java类库中有很多是实现了装饰器模式的类。比方说:在读取文件时
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
这其实就是一个decorator模式。因为针对File的读取方式有很多,如果每种都要采用继承的方法,那么会产生很多的子类,那样显然是很烦的。
          装饰器也称为油漆工模式。它的目的就是给一个对象动态地添加一些功能。就像是给对象刷了一层漆,使这个对象更加丰富,而不是通过继承来增加功能。而这些功能的添加是动态的运行期的,当然这里的动态并不是像aop中的引介introductor,大家不要混淆。
          在我们的项目中,经常会遇到日志的情况。大凡我们会定义一个log接口就像下面。
public interface Logger {
    public void log(String msg);
}
一般我们会把日志保存中文件中,所以有了一个FileLogger

public class FileLogger implements Logger {

 public void log(String msg) {
        //开始记录日志到文件中
 }
}
此时如果在项目有些地方需要对日志进行加密,有些地方又不需要加密,或者有些地方生成的文件是以xml的方式。此时如果采用继承的方法,也能实现,但是从面向对象的角度来说,并不建议对象的层次太深,增加系统的复杂性,这样对于系统的扩展和维护都不是很方便。此时Decorator模式就可以帮我们解决这些问题,我们可以为这个一般的FileLogger对象上刷一层不同的漆,那么这些漆,从上面增加的功能角度来说,就是加了一个“加密”的漆,或加了一层“生成xml”的漆。
先定义一个Decorator接口,此接口也实现了Logger接口
public class LoggerDecorator implements Logger{
   Logger logger;
   public LoggerDecorator(Logger logger){
        this.logger=logger;
   }
   //开始记录日志
   public void log(String msg){
       //此处便是给实现了Logger接口的,被刷了油漆的(增加了功能的例如加密等)对象记录日志
       logger.log(msg);
   }
}
public class EncryptDecorator extends LoggerDecorator{
    public EncryptDecorator(Logger logger){
        super(logger);
    }
    public void log(String msg){
        //刷加密字符串的油漆
        msg=this.encryptMsg(msg);
        //记录加密后的日志
        logger.log(msg);
    }
}
//客户端的调用
public DecoratorClient{
    public static void main(String args[]){
         Logger logger=new FileLogger();
         Logger decorator=new EncryptDecorator(logger);
         decorator.log("加密的字符串");
   }
}
这样就基本把Decorator模式的应用起来,当然在项目中我们可能还需要更丰富一下我们的类,此处仅用这样的简单示例来讲述。

posted @ 2008-08-18 23:11 周大侠 阅读(435) | 评论 (1)编辑 收藏

         网上google一下,想找一些有用的资料,结果是搜了不少,谁知道都是转载,而且相同的文章太多太多,达到了泛滥的地步,然后冒充自己的文章,也不提是转载,貌似增加了网络搜索资料的途径,实是浪费真正想找资料的朋友的时间,殊不知别人的时间都是有限的,每次打开一个页面结果却都是相同的内容,你叫人气不气,扰乱了整个网络的制序,损人利己,滥宇充数。
    网上的资料不是不可转载,但请转载者在盲目转载的同时,请提出自己的看法意见,留下有用的信息,否则乱贴在自己的blog只会让真正的有志之士所看不起,如果您无法原创,就请您把您的blog关闭。
    清除网络垃圾,还我们一片干净的网络空间!!!
posted @ 2008-08-15 23:35 周大侠 阅读(186) | 评论 (1)编辑 收藏

        Java中有关数据结构的类都在java.util包中,集合框架是每一个程序员都应该熟练掌握的一个类库。Java的集合框架可以提供处理对象的标准方式。在很早的jdk版本中,只提供了Dictionary、Vector、Stack、Properties来存储和操作对象。这些类之间没有统一的api,使用这些类达不到易扩展的作用。
        当然我们使用这些数据结构目的也是为了使用方便,能够提供高效的存取。学过数据结构的朋友们都知道,链表和哈希表的结构的效率都是较高的。为了使用不同的集合之间能够相互操作,相互扩展,那么使用通用的接口将是一个较好的选择。所以整个集合框架被设计成了一系列的标准的接口。在Collections类中有许多静态的算法方法。Iterator迭代器接口提供了通用的访问集合元素的方式,因为每一个集合都实现了Iterator接口。除了集合,还提供了映射的接口和类。比方说Map就提供了存储键值对。虽然它不是集合,但也被整合到了集合中。目前所有的集合都是基于泛型的。
        下面介绍集合框架中的几个常用的接口:
1.Collection 允许处理一组对象,位于集合层次结构的顶部
2.List  扩展Collection接口以处理序列
3.Queue  扩展Collection接口以处理列表中的特殊类型,其元素只能从前面删除
4.Set  扩展Collection接口以处理集合,集合中的元素必须是唯一的
5.SortedSet  扩展Set接口以处理排序的集合
当然除了上述的接口外,集合中还使用Copmarator、Iterator、ListIterator等接口 。
        Collection接口是构造集合框架的基础,必须被定义集合的任意类实现,同样它也是一个泛型接口。
方法摘要
 boolean add(E o)
          确保此 collection 包含指定的元素(可选操作)。
 boolean addAll(Collection<? extends E> c)
          将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
 void clear()
          移除此 collection 中的所有元素(可选操作)。
 boolean contains(Object o)
          如果此 collection 包含指定的元素,则返回 true
 boolean containsAll(Collection<?> c)
          如果此 collection 包含指定 collection 中的所有元素,则返回 true
 boolean equals(Object o)
          比较此 collection 与指定对象是否相等。
 int hashCode()
          返回此 collection 的哈希码值。
 boolean isEmpty()
          如果此 collection 不包含元素,则返回 true
 Iterator<E> iterator()
          返回在此 collection 的元素上进行迭代的迭代器。
 boolean remove(Object o)
          从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
 boolean removeAll(Collection<?> c)
          移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
 boolean retainAll(Collection<?> c)
          仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
 int size()
          返回此 collection 中的元素数。
 Object[] toArray()
          返回包含此 collection 中所有元素的数组。
<T> T[]
toArray(T[] a)
          返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
List接口:
该接口扩展了Collection接口,它声明集合是存储一个序列的元素。我们可以把它看成是动态数组。学过数据结构的朋友都知道,数组可以使用基于0的索引,对于泛型的List接口而言,他可以指定保存不同的对象类型。
方法摘要
 boolean add(E o)
          向列表的尾部追加指定的元素(可选操作)。
 void add(int index, E element)
          在列表的指定位置插入指定元素(可选操作)。
 boolean addAll(Collection<? extends E> c)
          追加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。
 boolean addAll(int index, Collection<? extends E> c)
          将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
 void clear()
          从列表中移除所有元素(可选操作)。
 boolean contains(Object o)
          如果列表包含指定的元素,则返回 true
 boolean containsAll(Collection<?> c)
          如果列表包含指定 collection 的所有元素,则返回 true
 boolean equals(Object o)
          比较指定的对象与列表是否相等。
 E get(int index)
          返回列表中指定位置的元素。
 int hashCode()
          返回列表的哈希码值。
 int indexOf(Object o)
          返回列表中首次出现指定元素的索引,如果列表不包含此元素,则返回 -1。
 boolean isEmpty()
          如果列表不包含元素,则返回 true
 Iterator<E> iterator()
          返回以正确顺序在列表的元素上进行迭代的迭代器。
 int lastIndexOf(Object o)
          返回列表中最后出现指定元素的索引,如果列表不包含此元素,则返回 -1。
 ListIterator<E> listIterator()
          返回列表中元素的列表迭代器(以正确的顺序)。
 ListIterator<E> listIterator(int index)
          返回列表中元素的列表迭代器(以正确的顺序),从列表的指定位置开始。
 E remove(int index)
          移除列表中指定位置的元素(可选操作)。
 boolean remove(Object o)
          移除列表中出现的首个指定元素(可选操作)。
 boolean removeAll(Collection<?> c)
          从列表中移除指定 collection 中包含的所有元素(可选操作)。
 boolean retainAll(Collection<?> c)
          仅在列表中保留指定 collection 中所包含的元素(可选操作)。
 E set(int index, E element)
          用指定元素替换列表中指定位置的元素(可选操作)。
 int size()
          返回列表中的元素数。
 List<E> subList(int fromIndex, int toIndex)
          返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
 Object[] toArray()
          返回以正确顺序包含列表中的所有元素的数组。
<T> T[]
toArray(T[] a)
          返回以正确顺序包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。
相对于Collection接口而言,List接口增加了add(int index, E element),add(int index,Collection c)方法,这些方法用于将元素插入到特定的位置,这也是动态数组的特性。
Set接口:
该接口扩展了Collection接口,但不允许有相同的存在的元素,而上述的List接口却没有此约束,其实很好理解,我们可以把它想象成数学中的集合,在那种集合中,是不允许有相同的元素的。
SortedSet接口扩展了Set接口,此接口是升序的集合,由于是有序的,所有自然其中的数据元素是有意义的,否则升序的算法无从使用起。自然就不能存在为null的对象。下表是该接口特有的方法:
方法摘要
 Comparator<? super E comparator()
          返回与此有序集合关联的比较器,如果使用元素的自然顺序,则返回 null
 E first()
          返回此有序集合中当前第一个(最小的)元素。
 SortedSet<E> headSet(E toElement)
          返回此有序集合的部分视图,其元素严格小于 toElement
 E last()
          返回此有序集合中最后一个(最大的)元素。
 SortedSet<E> subSet(E fromElement, E toElement)
          返回此有序集合的部分视图,元素范围从 fromElement(包括)到 toElement(不包括)。
 SortedSet<E> tailSet(E fromElement)
          返回此有序集合的部分视图,其元素大于或等于 fromElement
Queue接口:
这个接口在1.4的版本中是没有,新增的。看名字就知道是队列,先进先出。
方法摘要
 E element()
          检索,但是不移除此队列的头。
 boolean offer(E o)
          如果可能,将指定的元素插入此队列。
 E peek()
          检索,但是不移除此队列的头,如果此队列为空,则返回 null
 E poll()
          检索并移除此队列的头,如果此队列为空,则返回 null
 E remove()
          检索并移除此队列的头。
从队列顶部删除元素 。
posted @ 2008-08-15 19:03 周大侠 阅读(244) | 评论 (0)编辑 收藏

        AOP全称叫做Aspect-Oriented Programming,即面向方面编程或叫做面向切面编程。目前基于java的开源框架有很多已经应用了AOP思想进行设计开发。在轻量级的J2EE应用开发中,AOP经常可以解决一些系统级的服务,比方说事务处理、安全检查、系统日志等。
        目前在AOP编程开发中,有许多新的名词,这些名词的出现会让一些刚开始涉足AOP的朋友们是一头雾水。下面我会把每个名词的意思用自己的语言再描述一遍。
        关注点:关注点即是需要我们去解决的去关心的问题。关注点又可分为核心关注点和横切关注点。核心关注点指的是一个系统中的核心业务功能,也可以认为是是业务逻辑。横切关注点指的是充斥在各个核心关注点间的可以解决同一类问题的的关注点。那么我们的系统也可以认为是由若干个关注点组成的。
       连接点:连接点就是在程序运行时需要在某一点中插入切面,那一点就是连接点。这一点可以是一个方法、一个属性、构造函数、类静态初始化模块。在Spring框架中,只关注方法的切面,即只关心的是方法连接点。
        切入点:切入点其实就是连接点的集合。在Spring框架中我们经常可以看到利用正则表达式对切入点进行定义。
        通知:通知其实就是一个切面的具体实现。比方说在一个业务订单的处理中,切入了订单处理的日志,那么这个日志的具体实现就是一个advice。比方说这个日志实现了某人某时间进行订单的处理审批。那么通知有几种。有前通知、后通知、环绕通知、当然Spring框架中还有Exception通知。
        切面:上面讲到的切入点与通知就是切面的组成部分。
        引介:引介很强大,但是目前用的比较少。它可以强大到给一个定义好的类在运行时动态地添加方法、属性。
        织入:光有切面与核心关注点是不够的,因为这样两者还没有建立关系起来。那么织入的目的就是让两者建立起关系。织入也有三种方式:
1.通过Java代理实现织入。那么又有两种方式。一种是基于代理接口的Java动态代理。另一种是动态字节码生成器代理,也就是在spring中的经常发现的cglib.jar包。
2.有些Aop的实现织入采用了自定义的类加载器,在虚拟机加载字节码的时候进行织入。
3.最后一种就是使用专门的编译器来编译整个应用程序,在编译的过程中就进行织入。
        拦截器:拦截器故名思意就是进行拦截。它可以对连接点进行拦截。那么拦截器也可以组成链通常也称为栈。拦截器的说明可见我上一篇文章。
       
       
未完待续!
posted @ 2008-08-14 22:53 周大侠 阅读(250) | 评论 (0)编辑 收藏

     摘要:         本文为本人翻译struts2的官方网站上的关于拦截器的说明文档,官方网站上的说明均是英文的,不方便热爱学习而英语又不太好的朋友。该说明文档地址是http://struts.apache.org/2.0.11/docs/interceptors.html。     &nbs...  阅读全文
posted @ 2008-08-10 00:12 周大侠 阅读(3143) | 评论 (3)编辑 收藏

        Unified Modeling Language 的出现给当今面向对象的世界增添了浓墨淡彩的一笔。可视化的建模工具让开发人员丰富地表达了他们的想象力,并且以uml的方式向其他人展示。
        首先我们得理解什么是面向对象(Object Oriented)。对象是各种各样的实体,即是具体的事物也是抽象的事物。面向对象不光是对对象的属性和行为建模,它还包括其它方面。其中就有抽象、继承、多态和封装。抽象的概念很抽象,其意思是说抽象出你所需求的属性和操作,即是所需的东西。它是一种从一般的观点看事物的方法,焦点应该集中在事物的本质性质上,而不要过分地去追求细节,应该是抽象出一般化的东西。世界是复杂的,但不能因为它复杂就不去理解它,我们可以把它抽象化,其实抽象后世界也不大。
         继承:顾名思意就是子类拥有父类的所有的内部状态和运动规律。公共的东西可以被子类分享,正所谓,子又有孙,孙又有子,子子孙孙无穷溃也。当然不能像这样来设计。
         多态:多个形态,同样的一种动作,在不同的对象进行演绎的时候可能演绎的细节就会不一样。正所谓大家都喜欢吃,但是男人吃饭跟女人吃饭就不一样。男的可能吃的快吃的多,女的吃的少吃的慢,但大家都是吃这个动作,换了个对象来吃,就效果不一样。
         封装:举个例子,人们在看电视时,人们看到的是电视的屏幕,电视的按钮,至于屏幕为什么上面会有美女,按下按钮为什么会换台,人们好象不必去关心其是怎么工作的吧,当然也有闲人喜欢钻牛角尖。所以电视机就封装了如何让屏幕显示美女的工作。那么电视机的按钮和屏幕实际上就是电视机给我们这些喜欢看电视的人的接口。我们关心的也只是这些接口。至于这些接口怎么实现的,请交给厂家吧,世界也就是由若干个各司其职的人组成的。
          重载:说白了就是做同一件事的几种不同的方案。比方说:在公司加班,正常情况下,默认是吃盒饭,有一天老板归来,来一句走出去吃饭我请。如果用方法来表示的话就是public void eat(盒饭类 a) public void eat(饭店类a ,老板类b )。
          消息传递:在这个世界里,光有对象是不够的,那样人都是行尸走肉。对象之间是要相互协作的。那么相互协作之间是通过相互发送消息的方式。比方说看电视,我们使用遥控器打开电视。那么遥控器对象就向电视机对象发送了一个开机的消息。电视机对象接收了此消息后就打开了。
          正如世界是一个由若干个对象以及对象之间的若干个错综复杂的关系组成的。那么对象与对象之间又会有什么样的关系呢?打开电视时,我们说是你和电视机之间发了关联关系。再比方说你暗恋一个女生,你跟她之间形成了一个单向的关联关系。因为她不知道你暗恋她,当然你暗恋她,她也暗恋你的情况也有可能出现,此处我们不予探讨。如果她也暗恋你,那就是一个双向的关联关系。对象之间的依赖关系说明是目标对象与源对象之间的依赖关系。依赖就是当目标对象有所变化的时候源对象也相应的发生改变。
        收集系统需求时,把用户的业务需求转换成开发人员能够理解的需求,并最终把需求转化为代码。通过将需求映射为代码,可以保证代码满足这些需求,同时代码也可以回溯成需求。这样的过程就称为建模。建模过程的结果可以跟踪业务需求,到要求、到模型,到代码的全过程及其相反的过程,而不会在这个过程中迷路。
        可视化建模将模型中的信息用标准的图形元素直观的表示。这个标准的图形元素就是本文中提到的UML。它的出现为用户、开发人员、分析人员、测试人员、管理人员、需求调研人员等相关人员提供了沟通的桥梁。其中很直观的例子:对于用户来说,他更关心自己需要在这个系统中操作什么,以及这些操作是否满足了自己的业务需要,那么利用模型他可以直观的看到自己与这个系统的交互,根据这样的交互保证需求的获取。对于分析人员来说,他需要分析模型的对象之间的交互,以及这样的交互是否满足系统的需要,是否可以保证这样的交互对于业务的解析,解决自己分析时存在的疑惑,同时也可以根据模型交互的结果向需求调研人员提出问题。对于开发人员来说,他要考虑开发的对象以及这些开发对象需要完成的工作。对于测试人员来说,他们根据模型看到对象间的交互并且根据这些交互以及交互的产出准备测试用例。在RUP中就可以同步地进行测试了,而不是像瀑布模型那样最后才准备测试。对于项目管理人员来说,他需要看到系统中各个部分或者子系统之间的交互,在项目的实施过程根据计划看到各个系统模型完成的情况及相应的进度。对于公司的主管人员来说可能只需要看到更高层的模型,看到各个子系统运行情况结果。可视化的建模确实带来了系统的可控。通过先建模再编写代码,从一开始就保证了系统的结构合理。利用模型可以更方便地捕获设计缺陷,从而以较低的成本修正这些缺陷。
        Rational Rose是分析和设计面向对象软件系统的强大的可视化工具,可以用来先建模系统再编写代码,支持业务模型,帮助了解系统的业务,有助于系统分析,可以先设计使用案例和Use Case框图,显示系统的功能。也可以用Interaction框图显示对象之间如何配合,提供所需的功能。Calss框图可以显示系统中对象及其相互关系。Component框图可以演示类如何映射到实现组件。最后Deployment框图可以显示系统的网络结构。Rose模型的四个社图是:Use Case视图、Logical视图、Component视图和Deployment视图。每个视图针对不同对象,具有不同的用途。
        Use Case视图包括系统中的所有角色、使用案例和Use Case框图,还包括一些Sequence或Collaboration框图。该视图是系统中与实现无关的视图。该视图关注系统功能的高层形状,而不关注系统具体的实现方法。项目开始时,开发小组可以选择使用Use Case视图中生成业务模型,完成了业务模型后便是使用案例模型。客户、分析人员和项目经理利用使用案例、Use Case框图和使用案例文档来确定系统的高层视图。随着项目的进行,开发小组的成员也可以通过Use Case视图了解正在建立的系统的使用案例文档,通过使用案例描述事件流程。利用Use Case视图,测试人员开始编写测试脚本,技术人员开始编写文档。一旦用户同意了角色和使用案例,就确定了系统的范围。然后可以在Logical视图中继续开发,关注系统如何实现使用案例中提出的功能。
        Logical视图,关注系统如何实现使用案例中提出的功能。提供系统的详细图形,描述组件间如何关联,还包括特定的类、Class框图和StateChart框图,利用这些元素,开发人员可以构造出系统的详细设计。该视图关注的是系统的逻辑结构,在这个视图中,要标识系统组件,检查系统的信息和功能,检查组件之间的关系。
        Component视图,包括模型代码库,可执行文件,运行库和其他组件的信息。系统的Component视图可以显示代码模块间的关系。详细包括:组件,代码的实际模块;Component框图,显示组件及其相互关系;包,相关组件的组。该视图的主要用户是控制代码和编译部署应用程序的人。有些组件是代码库,有些是运行组件。
        Deployment视.图,关注于系统的实际部署。还包括容错,网络带宽,故障恢复和响应时间等。详细包括:进程,是在自己的内存空间执行的线程;处理器,任何有处理功能的机器;设备,包括任何没有处理功能的机器,如打印机。
        下面讨论UML以及UML的可视化工具给我们带来了什么样的好处。rose建立的业务模型关注系统针对的业务。业务模型包括:业务角色、业务用例、业务工人。业务模型研究的是业务的机构以及机构的角色。在建立业务模型的过程中,检查机构的结构和机构中的角色以及它们之间的相互关系,还需要介绍机构的工作流,公司中的主要过程,以及这些过程如何的工作,效率如何,是否有任何的瓶颈。简要的说就是要弄清楚业务的内部和外部,以及内外部如何进行通信。那么这些信息都将被记录在业务模型中。业务模型中框图有助于外部世界和机构的关系,以及机构如何完成这些目标。业务模型的主要工具之一是工作流框图。这些框图描述机构中的特定过程流程;显示这个过程中参与的人员,这个过程的步骤和参与这个过程的业务实体。业务过程建模人员首先用工作流框图建模当前过程,然后可以分析这些框图,寻找工作流中的缺陷和其他问题。完成业务模型的好处在于开始规划系统工作之前就完全了解了业务过程,这样就可以事先确定最需要自动化的工作流领域和系统中最有助于机构开发的部分从而建立对公司或者机构最有利的系统。
        实体类:实体类是要永久保存的信息。实体类通常在事件流和Interaction框图中,是对用户最有意义的类,通常用业务域术语来命名。边界类:边界类位于系统与外界的交界处,包括所以窗体、报表、打印机和扫描仪等硬件的接口以及与其他系统的接口。要寻找和定义边界类,可以检查Use Case框图。每个角色/用例 交互至少要有一个边界类。控制类:控制类负责协调其它类的工作。每个用例通常都有一个控制类,控制用例中的事件的顺序。在Interaction框图中,控制类具有协调责任。
       
 



















        
       
posted @ 2008-07-29 22:51 周大侠 阅读(168) | 评论 (0)编辑 收藏

SpringapplicationContext.xml中配置映射文件的方法:
1。减少配置文件里配置信息的数量
配置applicationContext.xml或者分布在其它的xml文件中的bean时,设置bean与bean之间的相互依赖关系是一件痛苦且容易出错的事。autowire属性的出现减轻了配置文件的容量。
<bean>的autowire属性有6个值。分别为:

No:即不启用自动装配。Autowire默认的值。

byName:通过属性的名字的方式查找JavaBean依赖的对象并为其注入。
byType:通过属性的类型查找JavaBean依赖的对象并为其注入。
constructor:通byType一样,也是通过类型查找依赖对象。
autodetect:在byTypeconstructor之间自动的选择注入方式。
default:由上级标签<beans>default-autowire属性确定。
在<beans default-autowire="byName">可以为本xml文件设置默认的自动装配的类型例如byName,当然在设置具体的<bean id="***" class="***" autowire="byType">时,会自动改变默认的byName为byType。
2。在web.xml中通过配置如下参数

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/*.xml</param-value>
    </context-param>   
会自动把WEB-INF/classes/sring目录下的所有以.xml结尾的文件加载spring容器进行管理,而不必手动编写每个applicationContex.xml,accessContext.xml等配置文件。
3。利用属性为mappingDirectoryLocation来配置相关的目录位置,从而避免为该目录下的所有文件名进行配置
<property name="mappingDirectoryLocation">
<list>
<value>classpath:/package1/<value>
</list>
</property>
如:
<!-- 设置Hibernate3的SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">net.sf.hibernate.dialect.SQLServerDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.generate_statistics">true</prop>
                <prop key="hibernate.connection.release_mode">auto</prop>
                <prop key="hibernate.autoReconnect">true</prop>
            </props>
        </property>
        <property name="mappingDirectoryLocations">       
            <list>      
               <value>classpath:com/apache/model</value>      
            </list>
        </property>   

    </bean>
4。消除ProxyFactoryBean的繁重配置
a.通过继承于parent ProxyFactoryBean
b.使用aop自动代理的方式
在Spring中进行事务的管理均是基于aop的方式,为每个需要事务管理的bean均设定相应的ProxyFactoryBean又是一件非常繁重的工作。使用自动代理可以消除这样的重复的工作。方法如下,声明DefaultAdvisorAutoProxyCreator为所有的advisor作为代理,在context上下文中查找所有的advisor,然后自动代理那些被在pointcut加入了切面的bean。针对事务使用spring中的事务的advisor,TransactionAttributeSourceAdvisor。
该advisor有两种方式进行注入,一种是setter方式,如下:
    <!-- 配置自动代理事务 -->
    <bean id="transactionAdvisor" class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
        <property name="transactionInterceptor" ref="transactionInterceptor"/>
    </bean>
另一种是constructor方式,如下:
    <!-- 配置自动代理事务 -->
    <bean id="transactionAdvisor" class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
     <constructor-arg>
        <ref bean="transactionInterceptor"/>
     </constructor-arg>        
    </bean>
建议以constructor方式进行注入。

posted @ 2008-07-28 23:04 周大侠 阅读(205) | 评论 (0)编辑 收藏

 

系统实现规范:以面向接口的方式进行编程。
下图为三层逻辑结构的简易关系图

 

 

以上是简易的系统逻辑结构,
***Action继承于xworkSupportAction,通过Spring来进行管理,在整个Spring的容器中,Spring负责管理整个系统的所有Bean,并负责初始化Bean之间的依赖关系。***Action中注入了服务层对象***ServiceImpl,ServiceImpl又注入了***DaoImpl对象。下面会逐步细化上面的关系图。

先看下面的web.xml配置

web.xml

    <display-name>Struts Blank</display-name>

    <context-param>

        <param-name>webAppRootKey</param-name>

        <param-value>wxy.root</param-value>

    </context-param>

    <!-- spring xml文件配置目录在class目录下的spring目录中WEB-INF/classes/spring -->

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>classpath*:spring/*.xml</param-value>

    </context-param>

    <!-- 配置log4j的日志信息WEB-INF/classes/config/log4j.properties -->

    <context-param>

        <param-name>log4jConfigLocation</param-name>

        <param-value>classpath*:config/log4j.properties</param-value>

    </context-param>

    <!-- 配置Character Encoding Filter -->

    <filter>

        <filter-name>encodingFilter</filter-name>

        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

        <init-param>

            <param-name>encoding</param-name>

            <param-value>UTF-8</param-value>

        </init-param>

    </filter>

    <!-- 配置Struts2 -->

    <filter>

        <filter-name>struts2</filter-name>

        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

    </filter>

    <filter-mapping>

        <filter-name>encodingFilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

    <filter-mapping>

        <filter-name>struts2</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

   

    <welcome-file-list>

        <welcome-file>index.html</welcome-file>

    </welcome-file-list>

    <!-- 载入Spring ApplicationContext -->

    <listener>

        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

    <!-- Spring 刷新Introspector防止内存泄漏 -->

    <listener>

        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>

    </listener>
未完待续.

 
posted @ 2008-07-28 22:15 周大侠 阅读(203) | 评论 (0)编辑 收藏

        一个软件的开发是一个极其复杂的过程,其中设计分析,设计、编码、测试、维护等,而系统分析却往往是一个软件成败的关键。
        如何进行系统分析,以及如何传递分析的的结果文档等,又是系统分析师的首要任务。系统分析对于任何人来说都不是容易 ,它没有规则的限定,它需要系统分析师的应变,虽然有相应的指导,但指导往往是教课书般,没有一个项目一尘不变地去原用教课书上的东西,更多的是经验。
        系统分析的成品即软件需求分析说明书,此书到底需要包括什么内容,到底是什么。这个问题很难回答,也许有很多人不加思索地可以答出,但我认为这个问题很难。这个由不同公司不同项目的具体情况决定的。从我的角度来看我觉得这个文档中的内容要走够设计师们看懂并可以作出设计。既然是为设计作打算,那么设计需要什么内容呢,这又涉及到设计方面的东西。
        需求来源于用户的一些“需要”,这些“需要”被分析,确认后形成完整的文档,该文档详细地说明了产品必须或应当做什么。如果只有一些零碎的对话、资料或邮件,就认为掌握了需求,那就是自欺欺人。需求是一个产品的源头,它的好坏对产品的影响最大,就像一条河流,如果源头被污染了,那么整条河流就被污染了。“用户”是一种泛称,可分为“客户”,最终用户或间接用户。需求分为两类,一类属于需求开发,另一类属于需求管理。需求开发分为需求调查、需求分析和需求定义。需求管理分为需求确认、需求跟踪和需求变更控制。需求开发的目的是通过调查与分析,获取用户需求并定义产品需求。需求调查的目的是通过各种途径获取用户的需求信息,产生《用户需求说明书》。需求分析的目的是对各种需求信息进行分析,消除错误,刻画细节等,常见的需求分析方法有“问答分析法”和“建模分析法”等。需求定义的目的是根据需求调查和需求分析的结果进一步定义准确无误的产品需求,产生《产品需求规格说明书》,系统设计人员依据《产品需求规格说明书》开展系统设计工作。需求管理的目的是在客户与开发方之间建立对需求的共同理解,维护需求与其它工作成果的一致性,并控制需求的变更。需求确认是指在开发方和客户共同对需求文档进行评审,双方对需求达成共识后作出书面承诺,使需求文档具有商业合同效果。需求跟踪是指通过比较需求文档和后续工作之间的对应关系,建立与维护“需求跟踪矩阵”,确保产品依据需求文档进行开发。需求变更控制是指依据“变更申请—审批—更改—重新确认”的流程处理需求的变更,防止需求变更失去控制而导致项目发生混乱。
         如何进行需求分析是需求调研中最重要的一步。需求分析是指在需求开发过程中,对所获取的需求信息进行分析,及时排除错误和弥补不足,确保需求文档正确的反映用户的真实意图。分析方法大体有两类:“问答分析法”和“建模分析法”。问答分析法:刨根究底地问,如果问题都被解答了,那么需求也就分析清楚了。建模分析法是指用图形符号来表示、刻画需求。
         在系统分析中,用例的重要性不用多说。真正理解了用例,懂得利用用例来驱动项目的开发,才能真正把握住需求的精髓。每个用例是一组场景的集合,而每个场景又是一个步骤序列。用例图通常是供客户和开发组参考的设计文档的一部分。用例之间可以以两种方式相互关联,一种方式是包含,即在一个用例中重用另一个用例中的步骤。另一种方式叫扩展,允许通过对已有用例增加步骤创建一个新的用例。用例之间的另外两种关系是泛化和分组。泛化是指一个用例继承了另一个用例。分组是一组用例的简单组织方式。 
       用例可以解释为某个参与者要做的一件事。也可以解释为一系列完成一个特定目标的“功能”的组合。这一件事可以解释为:1.这件事是相对独立的。它不需要与其他用例交互而独自完成参与者的目的。2.这件事的执行结果对于参与者来说是可观测的和有意义的。3.这件事必须由一个参与者发起,不存在没有参与者的用例。4这件事是以短宾短语出现。即这件事必须有一个动作和动作的受体。用例的背后是一种需求方法论。用例的核心是以参与者为核心,从参与者的角度描述他的日常工作,并分析这些日常工作是如何交互的。用例的首要目的不是要弄清楚某项业务是如何一步步完成的,而是要弄清楚有多少参与者?每个参与者都做什么?
         需求分析需要经过业务建模、用例分析和系统建模三部分组成。1.业务建模的目标是通过用例模型的建立来描述用户需求,需求规格说明书通常在这个阶段产生。2.用例分析是分析员用OO的方法来分析业务用例的过程,这个阶段称为概念模型阶段,这个阶段通常使用无类型的用例。3.系统建模是将用户的业务需求转化为计算机实现的过程,这个阶段通常使用无类型的用例和用例实现两种类型。系统范围、项目计划和系统架构通常在这个阶段形成雏形。业务用例(business usecase),是用来描述用户原始需求的,它的含义是站在用户的角度,使用用户的业务术语来描述用户在其领域所做的事。业务用例命名,描述都必须采用纯业务语言,不能出现计算机术语。业务模型是系统分析员和用户讨论需求,达到一致理解的基础。只有完成下面的工作,才能算是业务模型已经建立完成。1.发现和定义
       
posted @ 2008-06-18 11:35 周大侠 阅读(394) | 评论 (0)编辑 收藏

1.使用@AspectJ标签
   在AspectJ5中增加了对Java5注解的完全支持,可以使用Java注解来取代专门的AOP语法,把普通的Java类(POJO)声明为切面模块。使用<aop:aspectj-autoproxy/>来开启在POJO中通过注解来标识切面模块的识别功能。但目前Spring只支持其中部分标签,包括@Before,@AfterReturning,@AfterThrowing,@After,@Around等几种。
2.基于Schema模式配置Spring AOP
通过Spring配置文件中通过AspectJ切入点语言表达式来定义切入点,并配置相关的增强Advice实现方法
<aop:config>
    <aop:pointcut id="somePointcut" ../>
    <aop:advisor id="someAdvisor" ../>
    <aop:aspect id="someAspect" ref="someBean">
        <aop:adviceType id="someAdvice" ../>
    </aop:aspect>
</aop:config>
3.基于Spring API的配置文件
包括如下内容:
1.0个或多个切入点定义Bean,必须实现Pointcut接口
2.1个或多个通知实现Bean,必须实现Advice接口
3.0个或多个引介Bean,实现IntroductionInfo接口
4.1个或多个切面封装Bean,必须实现Advisor接口
5.1个或多个真实业务Bean
6.1个或多个代理Bean
posted @ 2008-06-15 16:53 周大侠 阅读(3542) | 评论 (0)编辑 收藏

1.形式多样的交流激发每个人的潜能
2.不可缺少的周末总结交流
3.改善工作环境,排除干扰
4.合理制定进度计划,不提倡加班
posted @ 2008-06-15 16:10 周大侠 阅读(180) | 评论 (0)编辑 收藏

这里所说的Portal是指JCP-JSR168规范所描述的:Portal是一个基于Web的应用,通常它提供个性化、单点登录、内容集成和显示等功能。Portal技术包括三个方面:

1)  Portal服务器(Portal Server);

2)  Portlet容器;(Portlet Container)

3)  Portlet。

1) Portal Server 的定义是

一个 Portal(门户网站)就是指一个 Web-based 的系统,通常都会提供个人化设置、单一登陆、以及由各种不同来源或不同网站取得各式各样的信息,并且将这些信息放在网页之中组合而成的呈现平台,门户网站会有精巧的个人化设置去提供定制的网页,当不同等级的使用者来浏览该页面将获得不同的信息内容。

负责接收HTTP请求,调用portlet,并将portlet产生的内容聚集到portal page返回给客户。

2) Portlet Container 的定义是

portlet container 是提供 portlets 执行的环境,包含了许多 portlets 并且管理他们的生命周期,他也会永远保存着 portlets 的喜好设置,一个 portlet container 接收到来自 portal 的请求后,接着将这个请求传递给存在 container 的 portlet 执行。portlet container 没有义务去组合 portlets 产生的信息內容,这个工作必须由 portal 来处理。portal 和 portlet container 可以放在一起视为同一个系统的组件,或者分开成为两个独立的组件。

负责提供portlet的运行时环境,管理portlet的生命周期,还负责提供portlet持久化能力。

3) Portlet 的定义是

一个 Portlet 是以 Java 技术为技术的 Web 组件,由 Portlet Container 所管理,专门处理客户的 request 以及产生各种动态的信息内容。Portlets 为可插式 ( pluggable ) 的客户界面组件,提供呈现层成为一个信息系统。这些由 portlet 产生的内容也被称为片段 (fragment),而片段是具有一些规则的Markup( HTML、XHTML、WML ),而且可以和其他的片段组合而成一个复杂的文件。而 Portlet 中的内容正常来说是与其他 Portlet 的内容聚合而成为一个 Portal 网页。而 Portlet 的生命周期是被 Portlet Container 所管理控制的。客户端和 portlets 的互动是由 portal 通过典型的 request/response 方式实现,正常来说,客户会和 portlets 所产生的内容互动,举例来说,根据下一步的连接或者是确认送出的表单,结果 portal 将会接收到 portlet 的动作,将这个处理状况转向到目标 portlet。这些 portlet 内容的产生可能会因为不同的使用者而有不同的变化,完全是根据客户对于这个 portlet 的设置。

Portal主要是解决企业信息和应用的前端集成问题,它负责连结企业后台EAI,集成企业的结构和非结构化信息,并提供统一的访问企业信息和应用的入口。

(摘自JSR168规范文档)

portlet 与 servlet 的关系
Portlet 和 Servlet 算是兄弟有那么一点点相似却又有那么一点点不同,因为 Servlet 和 Portlet 不尽然相同,所以研究小組決定将 portlets 定义成为一个新的组件,因此定义了 portlets 一个新的并且明确的界面与行为。为了尽可能与现有的 servlet 结合达到重复使用的目的,portlet 的规范利用了 servlet 的规范,许多观念都很相似的,结合 portlets、servlets 及 jsp 在同一个网站系统中,我们称为 portlet application 。在同一个 portlet application 中,他们将分享同一个 classloader,context 及 session。

1) Portlet 和 Servlet 的相似之处

@ portlets 也是 Java 技术的 web 组件
@ portlets 也是有特定的 container 在管理
@ portlets 可以动态产生各种内容
@ portlets 的生命周期由 container 所管理
@ portlets 和客户端的互动是通过 request/response 的机制

2) Portlet 和 Servlet 也有一些不同

@ portlets 只产生 markup 信息片段,不是完整的网页文件。而 Portal 会将所有的 Portlet markup 信息片 段放到一个完整的 Portal 网页。
@ portlets 不会和 URL 有直接的关系
@ 客户端必须通过 portal 系统才能和 portlets 互动
@ portlets 有一些定义好的 request 处理,action request 以及 render request。
@ portlets 默认定义 portlet modes 及窗口状态可以指出在网页中该 portlet 的哪个功能正在执行及现在的 状态。
@ portlets 可以在同一个 portal 网页之中存在多个。

3) Portlet 有一些附加的功能是 Servlet 所没有的

@ Portlets 能够存取及储存永久配置文件及定制资料。
@ portlets 可以存取使用者数据
@ portlets 具有 URL 的重写功能在文件中去动态建立连结,允许 portal server 不用去知道如何在网页的片 段之中建立连结及动作。
@ portlets 可以储存临时性的数据在 portlet session 之中,拥有两个不同的范围:
application-wide scope 及 portlet private scope 。

4) Portlet 不具有一些功能, 但是 Servlet 却有提供

@ servlet 具有设置輸出的文字编码( character set encoding)方式
@ servlet 可以设置 HTTP 输出的 header
@ servlet 才能夠接收客户对于 portal 发出的 URL 请求

基于Portal开发项目的优势
1、可以与以后新开发的或已集成到Portal中的企业应用实现无缝集成。

2、可以分享Portal服务器和Portlet容器提供的种种功能。这要视Portal服务器提供商而定。

3、由于Portlet已规范化(JSR168),所以应用中开发的Portlet可以部署在不同的Portal服务器上。

 
posted @ 2008-03-30 17:24 周大侠 阅读(260) | 评论 (0)编辑 收藏