3.2 aop容器的详细设计:
a. XML文件:记录配置信息。文件映射类:负责读入XML文件并将文件映射成配置类。(XmlDataLoader,AopDefinitionLoader,)
public interface AopDefinitionLoader extends XmlDefinitionLoader{
ArrayList getJoinpoints();
}
b. 配置类:aop概念映射。(joinpoint,pointcut,advice)
public interface Joinpoint {
TargetObjectMatcher getTargetObjectMatcher();
Interceptor getInterceptor();
String getType();
}
public interface Pointcut {
String getTargetClass();
Advice[] getMatchAdvice(Method method);
}
public interface Advice {
String getType();
void proceed() throws AspectException;
}
public interface AfterAdvice extends Advice{
}
public interface BeforeAdvice extends Advice{
}
public interface ThrowsAdvice extends Advice{
}
public interface AroundAdvice extends Advice{
}
c. 代理类:生成代理对象。(DynamicAopProxy)
public class DynamicAopProxy extends DynamicProxy implements InvocationHandler{
protected Object obj;
protected Pointcut pointcut;
private DynamicAopProxy(Object targetObject, Pointcut targetPointcut) {
this.obj = targetObject;
this.pointcut = targetPointcut;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result;
Advice advice;
advice = this.getTargetAdvice(AdviceType.BEFOREADVICE, m);
try{
advice.proceed(obj,m,args);
}
catch(AspectException ex){
ex.printStackTrace(System.out);
}
advice = this.getTargetAdvice(AdviceType.AROUNDADVICE, m);
try{
result = advice.proceed(obj,m,args);
}
catch (AspectException ex) {
ex.printStackTrace();
}
catch (Exception e) {
advice = this.getTargetAdvice(AdviceType.THROWSADVICE, m);
try {
advice.proceed(obj,m,args);
} catch (AspectException e1) {
e1.printStackTrace();
}
throw new RuntimeException
("unexpected invocation exception: " + e.getMessage());
}
finally {
System.out.println("end method " + m.getName());
}
advice = this.getTargetAdvice(AdviceType.AFTERADVICE, m);
try {
advice.proceed(obj,m,args);
} catch (AspectException e) {
e.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
return result;
}
public Advice getTargetAdvice(String type, Method m){
Advice[] advices = pointcut.getMatchAdvice(m);
for(int i=0; i<advices.length;i++){
if(advices[i].getType() == type){
return advices[i];
}
}
return new DummyAdvice();
}
public static Object newInstance(Object obj) throws FatalProxyException {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new DynamicAopProxy(obj, null));
}
}
d. 拦截器:方法拦截对象。(Interceptor, Invocation)
public interface Interceptor{
public Object invoke(Invocation invocation) throws InvocationException;
public Interceptor getNext();
public Interceptor setNext(final Interceptor interceptor);
}
public interface Invocation {
Object getTargetObject();
Method getTargetMethod();
Object proceed();
}
3.3 补充说明:
AOP作为当前最新的技术,成功的解决了系统的紧密耦合度问题。现有世界提供此技术的主流产品不多,AspectJ、JBoss和Spring是它们的代表性作品。三个产品实现的技术也不相同。
三、 软件工程实践
3.1 Principles of OOD and Packge:
SRP单一职责原则:
就一个类而言,应该仅有一个引起变化的原因
OCP开放-封闭原则:
软件实体应该可以扩展,但是不可修改
LSP Liskov替换原则:
子类型必须能够替换它们的基类型
DIP依赖倒置原则:
抽象不应该依赖于细节,细节应该依赖于抽象
ISP接口隔离原则:
不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于所在的类层次结构
REP重用发布等价原则:
重用的粒度就是发布的粒度
CCP共同封闭原则:
包中的所有类对于同一性质的变化应该是共同封闭。一个变化如果对一个包产生影响,则将对该包中的所有类产生影响,而对于其他包不造成任何影响。
CRP共同重用原则:
一个包中所有类应该是共同重用。如果重用了包中一个类,那么就要重用该包中的所有类。
ADP无环依赖原则:
在包中的依赖关系图中不允许存在环。
SDP稳定依赖原则:
朝着稳定的方向进行依赖
SAP稳定抽象原则:
包的抽象程度应该和其稳定程度一致。
这些原则是数十年来软件工程经验来之不易的成果。我们采用它们来指导我们的设计。如果说模式是一种结构的话,那么这些原则是结构的内在本质。这些原则有助我们消除设计中的不合理,并为当前特性集构建出最好的设计。
3.2 Iterator、Refactor与Pattern
本系统中实现了大量的模式。但是这些模式并没有在一个开始就设计并实现。实际上,在系统刚刚开始设计时,我们决心不特意使用这些模式。这并不是我们否定设计模式的优势,相反我们认为设计模式将为我们的开发带来质的改变。设计模式给我们的,不仅仅是一些问题的解决方案,更有追求完美「理型」的渴望。但是,Joshua Kerievsky在那篇著名的《模式与XP》(收录于《极限编程研究》一书)中明白地指出:在设计前期使用模式常常导致过度工程(over-engineering)。这是一个残酷的现实,单凭对完美的追求无法写出实用的代码,而「实用」是软件压倒一切的要素。从一篇《停止过度工程》开始,Joshua撰写了"Refactoring to Patterns"系列文章。这位犹太人用他民族性的睿智头脑,敏锐地发现了软件的后结构主义道路。而让设计模式在飞速变化的Internet时代重新闪现光辉的,又是重构的力量。
系统每次迭代原因有两种:需求变化和技术改进。最初系统的需求只是概念性的,每一次需求的细化,必然要求系统迭代以适应需求。技术改进的也会进行迭代。每次技术的实现在开始时候只是很简单的满足功能,随着系统发展,原来很多不满足的OOD原则的代码将被Refactor,同时也是系统进入迭代,因为模块的一个职责是和阅读它的人进行沟通,一个无法沟通的模块是拙劣的。
四、 总结
作为服务器端组件体系的一个实现,本文所展示的无疑相当的拙劣。由于时间的原因和自身实力的问题,在很多问题上处理欠妥当。在未来的实践中希望能够加以改善。
但是,本文对于容器与组件的核心技术做了初步涉及和讨论。这些技术包括:IoC反转、生命周期管理、AOP等。而另外的技术如:事务管理、安全验证等它们可以利用AOP技术提供,本文因为时间上的缘故没有完成这个实践;另外一个重要的技术——数据库连接池技术本身可以作为容器资源的一部分通过组件上下文环境提供给组件。
另外一个需要补充说明的是容器和框架关系。容器通常被称为元框架。基于容器之上开发人员可以加上许多控制技术如果工作流系统、MVC系统。
五、 致谢语
感谢厦门大学软件学院,注重实践和动手能力的教学体制让我有了很多的实践机会,为这次毕业设计奠定了基础,也从而让我在这次毕业实践中能充分展示以前的经验和积累的知识。
本次毕业设计实在我的导师董老师和夏侯老师的亲切关怀和悉心指导下完成的。两位老师为我们提供了良好的设计环境,并给予论文工作以方向性的指导,让我们少走了很多的弯路,从他身上不仅学到了科学知识,而且他严谨的治学态度和认真的工作作风使我受益非浅。其中夏侯老师还特意到我的实习公司,和我的P.M.交换意见。
此外,非常感谢我的P.M.曾磊和我的mentor黄厉。在毕业设计过程中,他们都给我很大帮助,为我提供了非常宽松的工作环境。同时感谢公司的同事们,尤其是warren,在每周四举行的software club活动上一起讨论各种技术,这使我受益非浅。再次感谢他们。
感谢我同组的武豹和蔡舒达同学,我们经常在一起讨论研究设计过程中的难题,在整个的毕业设计过程中给了我很大的帮助。经过共同的努力,使我们小组能发挥出集体的力量较好的完成实习任务。
参 考 文 献
1. Ed Roman, Scott Ambler,Tyler Jewell.《Mastering Enterprise JavaBean》. USA. Wiley Computer Publishing 2002.
2. Markus Volter, Alexander Schmid, Eberhard Wolff. 《Server Component Patterns Component Infrastructures Illustrated with EJB》. USA . Wiley Computer Publishing 2002.
3. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. 《Design Patterns Elements of Reusable Object-Oriented Software》. USA . Addison Wesley 1994.
4. Robert C. Martin 《Agile Software Development》.USA. Printice Hall 2003
5. Grady Booch 《Object-Orineted Analysis and Design with Applications 》 .USA. Addison Wesley 1994.