JDK 5.0以来推出Annotation.

已经有很多文章介绍怎么使用 Annotation,这里我也不多说了

其中可以查到 Annotation是可以打在Package上的.可是却很少看到介绍怎么在Package上打Annotation

这里我就说一下:

首先在Package下建个文件package-info.java

在这个java文件中

输入

@Simple(value = "package")//我自己定义的Annotation

package com.annotation;//当前的Package

 

OK完成,很简单吧

 

看看怎么调用,在  com.annotation下有个Test.java

 

Simple s = Test.class.getPackage().getAnnotation(Simple.class);

System.out.println(s.value());

 

可以看到打印出 package了吧!

S.O.D.A. 全称 Simple Object Database Access

Simple Object Database Access(S.O.D.A)API是Carl Rosenberger创建的,他也是db4o的创建者

S.O.D.A. 是用于数据库交流的对象接口(API).

目前S.O.D.A.只定义了查询接口,由以下几个接口组成:

Constraint(定义了约束)

Constraints(约束的集合)

Query(定义了查询节点)

Candidate(封装了查询结果对象用于在Evaluation中调用)

Evaluation(用在查询最后被回调来筛选数据)

ObjectContainer(定义数据容器,用于生成Query)

ObjectSet(Query返回的结果集)

运用S.O.D.A,你可以动态地构建查询。查询API的基本框架就是查询图表(query graph)。

查询图表(query graph)这个词就很形象的描述了S.O.D.A.所需要的数据结构.

一开始我是以树的方式去理解S.O.D.A.的结构,虽然是可以这样实现这个接口但最后去解析计算其树的路径就极其复杂.

既然计算树的路径复杂,那就不去计算,一开始就以一个约定的方式保存好路径,直接使用这个路径就可以了.

这样这个结构就变成一个图表的形式的,比如Query可以看成图表中的一条记录,Query通过不断descend指定的节点路径就相当于表的序号,Query通过constrain约束的条件就是一条记录的内容,而Constraint之间的and/or关系就是记录之间的关系,这样比较容易就可以实现S.O.D.A了

思想是,将这个查询图表(这里是一个Map),不断的通过descend传承下去,所有的Constraint和节点路径都放在查询图表中,而最后只要取出查询图表,那所有的关系都一目了然了.

这里附上一个简单的实现代码:

Query 的实现:

/**

 * 面向DAO的,采用SODA方式进行查询 此Query的用法和标准的SODA稍有不同

 * 此Query不能指定根查询节点的约束.此节点的约束由DAO指定(因为DAO使用了泛型,若此处指定的话,泛型cast的时候就会抛CastError的异常)

 *

 * @author Kevin.Huang

 * @date 2007-9-30

 */

public class ZQuery implements Query {

/**

 * 此节点对应的域

 */

private String field = null;

/**

 * 所有的约束的集合

 */

private MultiMap constraints;

private List< ZOrder > orders;

private List< ZComparator > comparators;

/**

 * 父节点

 */

private ZQuery parentQuery;

/**

 * 子节点

 */

private Map< String, ZQuery > querys = new HashMap< String, ZQuery >();

public ZQuery() {

this.constraints = new MultiValueMap();

this.orders = new ArrayList< ZOrder >();

this.comparators = new ArrayList< ZComparator >();

}

protected ZQuery(String field, ZQuery parentQuery) {

this.field = field;

this.parentQuery = parentQuery;

this.constraints = parentQuery.getConstraint();

this.orders = parentQuery.getOrders();

this.comparators = parentQuery.getComparators();

}

public Constraint constrain(Object constraint) {

if (field == null) {

throw new RuntimeException("The Root Query Node can constraint only one condition!");

}

ZConstraint c = new ZConstraint(this, constraint);

constraints.put(this.field, c);

return c;

}

@SuppressWarnings("unchecked")

public Constraints constraints() {

return new ZConstraints((Collection< ZConstraint >) constraints.get(this.field));

}

public Query descend(String fieldName) {

if (querys.keySet().contains(fieldName)) {

return querys.get(fieldName);

} else {

ZQuery q = new ZQuery((this.field == null ? fieldName : (this.field + "." + fieldName)), this);

querys.put(fieldName, q);

return q;

}

}

public Query orderAscending() {

if (field == null) {

throw new RuntimeException("The Root Query Node cannot make order!");

}

this.orders.add(new ZOrder(this.field, true));

return this;

}

public Query orderDescending() {

if (field == null) {

throw new RuntimeException("The Root Query Node cannot make order!");

}

this.orders.add(new ZOrder(this.field, false));

return this;

}

@SuppressWarnings("unchecked")

public Query sortBy(Comparator comparator) {

this.comparators.add(new ZComparator(this.field, comparator));

return this;

}

/**

 * @return the field

 */

public String getField() {

return field;

}

/**

 * @return the constraints

 */

public MultiMap getConstraint() {

return constraints;

}

/**

 * @return the querys

 */

public Map< String, ZQuery > getQuerys() {

return querys;

}

/**

 * @return the parentQuery

 */

public ZQuery getParentQuery() {

return parentQuery;

}

/**

 * @return the orders

 */

public List< ZOrder > getOrders() {

return orders;

}

/**

 * @return the comparators

 */

public List< ZComparator > getComparators() {

return comparators;

}

}

Constraint的实现:

/**

 * @author Kevin.Huang

 * @date 2007-9-30

 */

public class ZConstraint implements Constraint {

/**

 * constant defination : value of "=" sql operator

 */

public static final String EQUAL = "equal";

/**

 * constant defination: value of "!=" sql operator

 */

public static final String NOT = "not";

/**

 * constant defination: value of ">=" sql operator

 */

public static final String GREATER = "greater";

/**

 * constant defination: value of "<=" sql operator

 */

public static final String SMALLER = "smaller";

/**

 * constant defination: value of "between" sql operator

 */

public static final String CONTAINS = "contains";

/**

 * constant defination: value of "like" sql operator

 */

public static final String LIKE = "like";

/**

 * constant defination: value of "startsWith" sql operator

 */

public static final String STARTSWITH_TRUE = "startsWith:true";

/**

 * constant defination: value of "startsWith" sql operator

 */

public static final String STARTSWITH_FALSE = "startsWith:false";

/**

 * constant defination: value of "endsWith" sql operator

 */

public static final String ENDSWITH_TRUE = "endsWith:true";

/**

 * constant defination: value of "endsWith" sql operator

 */

public static final String ENDSWITH_FALSE = "endsWith:false";

/**

 * 此约束所在的Query节点

 */

private ZQuery query;

/**

 * 次约束的基准值

 */

private Object value;

private List< ZConstraintLink > zConstraintLinks = new ArrayList< ZConstraintLink >();

/**

 * 关联的约束

 */

private Collection< String > conditions = new ArrayList< String >();

protected ZConstraint(ZQuery query, Object value) {

this.query = query;

this.value = value;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#and(com.infowarelab.zephyr.domain.soda.Constraint)

 */

public Constraint and(Constraint with) {

zConstraintLinks.add(new ZConstraintLink(ZConstraintLink.TYPE_AND, (ZConstraint) with));

return this;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#contains()

 */

public Constraint contains() {

String[] c = {NOT };

if (conflictOnly(c)) {

throw new ConstraintConditionWrongException("contains  only can with not!");

}

this.conditions.add(CONTAINS);

return this;

}

public Constraint endsWith(boolean caseSensitive) {

String[] c = {NOT };

if (conflictOnly(c)) {

throw new ConstraintConditionWrongException("endsWith  only can with not!");

}

if (caseSensitive) {

this.conditions.add(ENDSWITH_TRUE);

} else {

this.conditions.add(ENDSWITH_FALSE);

}

return this;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#equal()

 */

public Constraint equal() {

String[] c = {EQUAL, LIKE, CONTAINS, ENDSWITH_TRUE, ENDSWITH_FALSE, STARTSWITH_FALSE, STARTSWITH_TRUE };

if (conflictExist(c)) {

throw new ConstraintConditionWrongException(

"equal can't with contains , endsWith, startsWith, like or himself!");

}

this.conditions.add(EQUAL);

return this;

}

/**

 * @return the conditions

 */

public Collection< String > getConditions() {

return conditions;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#getObject()

 */

public Object getObject() {

return this.value;

}

/**

 * @return the query

 */

public ZQuery getQuery() {

return query;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#greater()

 */

public Constraint greater() {

String[] c = {GREATER, LIKE, CONTAINS, ENDSWITH_TRUE, ENDSWITH_FALSE, STARTSWITH_FALSE,

STARTSWITH_TRUE };

if (conflictExist(c)) {

throw new ConstraintConditionWrongException(

"greater can't with contains , endsWith, startsWith, like or himself!");

}

this.conditions.add(GREATER);

return this;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#like()

 */

public Constraint like() {

String[] c = {NOT };

if (conflictOnly(c)) {

throw new ConstraintConditionWrongException("like  only can with not!");

}

this.conditions.add(LIKE);

return this;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#not()

 */

public Constraint not() {

if (conditions.contains(NOT)) {

throw new ConstraintConditionWrongException("not already exist!");

}

this.conditions.add(NOT);

return this;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#or(com.infowarelab.zephyr.domain.soda.Constraint)

 */

public Constraint or(Constraint with) {

zConstraintLinks.add(new ZConstraintLink(ZConstraintLink.TYPE_OR, (ZConstraint) with));

return this;

}

/*

 * (non-Javadoc)

 *

 * @see com.infowarelab.zephyr.domain.soda.Constraint#smaller()

 */

public Constraint smaller() {

String[] c = {SMALLER, LIKE, CONTAINS, ENDSWITH_TRUE, ENDSWITH_FALSE, STARTSWITH_FALSE,

STARTSWITH_TRUE };

if (conflictExist(c)) {

throw new ConstraintConditionWrongException(

"Smaller can't with contains ,endsWith, startsWith, like or himself!");

}

this.conditions.add(SMALLER);

return this;

}

public Constraint startsWith(boolean caseSensitive) {

String[] c = {NOT };

if (conflictOnly(c)) {

throw new ConstraintConditionWrongException("endsWith  only can with not!");

}

if (caseSensitive) {

this.conditions.add(STARTSWITH_TRUE);

} else {

this.conditions.add(STARTSWITH_FALSE);

}

return this;

}

private boolean conflictExist(String[] conditionStrings) {

for (String conditionString : conditionStrings) {

if (conditions.contains(conditionString)) {

return true;

}

}

return false;

}

private boolean conflictOnly(String[] conditionStrings) {

for (String existCondition : conditions) {

for (String conditionString : conditionStrings) {

if (existCondition.equals(conditionString)) {

return true;

}

}

}

return false;

}

/**

 * @return the zConstraintLinks

 */

public List< ZConstraintLink > getZConstraintLinks() {

return zConstraintLinks;

}

}

Groovy是构建在JVM上的一个轻量级却强大的动态语言.因为Groovy就是用Java写的,Groovy可以做到与Java的无缝兼容,可以使用Java强大的类库 而且Groovy最终也会被编译成class文件.

Groovy在1.0版的时候还存在性能问题,因为Groovy的很多实现都是用反射来做的,但是现在Groovy 1.1快推出了,据说快了10x…现在JetBrains也加入了Groovy Team旨在改善Groovy的性能,在Groovy2.0的时候还可能加上JIT,那性能就不成问题了,看来Groovy已经不是小打小闹了.而且随之而来的Grail.等基于Groovy的框架的推出,Groovy前景一片大好啊.

这篇文章不是为了讲Groovy的一些语法,而是说他怎么和Java做整合.

  • 静态使用Groory

1.运行Groovy类.

Groovy最终是会被编译成Java 的Class类的,所以Java是可以直接使用Groovy的类的.

如下,先是一个Groovy类:

package com.test;

class TestGroovyHelloWorld {
def doit(){
println "hello world!"
}
}

此类定义了一个doit方法,打印出hello world!字符串

然后看看Java怎么用这个类:

package com.test;

public class TestHelloWorld {

/**

  • @param args
    */
    public static void main(String[] args) {
    TestGroovyHelloWorld test = new TestGroovyHelloWorld();
    test.doit();

}

}

运行一下,果然打出了hello world!

很简单吧,只要直接import就行了.hoho,而且定义一个GroovyBean比定义一个JavaBean要简单的多的多.

2.运行Groovy脚本

实际上和Groovy类差不多,只不过Groovy类是集成自GroovyObject,而Groovy脚本是集成GroovyScript的,实际看看例子吧

Groovy脚本:

package com.test;

println "$test hello world!"

也很简单,就是打出hello world!不同的时候前面加上了$test ,这个有点类似与FreeMarker的格式($test也可以写成${test}),作用也是一样,通过外部将test参数引入,可以将$test替换成一个对象.看看下面Java怎么做的吧:

public class TestMain {

/**

  • @param args
    */
    public static void main(String[] args) {
    Binding b = new Binding();
    b.setVariable("test", "Kevin");//向脚本中的$test传入对象"Kevin"
    Script test = new TestScript(b);
    test.run();
    }
    }

打印出来一看是Kevin hello world!了..

  • 动态使用Groovy

Groovy是一个动态的脚本语言,如果只是向上面那样静态的使用,那优势就少了一半,既然是动态语言,那就看看怎么动态的去使用Groovy吧

1.通过接口,动态载入并使用Groovy类

(1)、定义Java接口包含在Java中需要调用的Groovy方法

public interface IFoo {
public Object run(Object foo);
}

(2)、创建Groovy类实现该接口

class Foo implements IFoo {
public Object run(Object foo) {
println ‘Hello World!’
x = 123
foo * 10
}
}

(3)、动态载入Groovy类,创建接口实例,调用接口中定义的方法

import groovy.lang.GroovyClassLoader;
import java.io.File;
public class InvokeGroovy {
public static void main(String[] args) {
ClassLoader cl = new InvokeGroovy().getClass().getClassLoader();
GroovyClassLoader groovyCl = new GroovyClassLoader(cl);
try {
Class groovyClass = groovyCl.parseClass(new File("src/Foo.groovy"));
IFoo foo = (IFoo) groovyClass.newInstance();
System.out.println(foo.run(new Integer(2)));
} catch (Exception e) {
e.printStackTrace();
}
}
}

上面的方法是通过定义好接口来动态载入,如果没有接口怎么办…办法还是有的,那就是传说中的反射..Groovy也支持反射哦

2.通过反射,动态载入并使用Groovy类

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import java.io.File;
public class DynamicGroovy {
private GroovyObject groovyObject;
public Object getProperty(String name) {
return groovyObject.getProperty(name);
}
public Object invokeScriptMethod(String scriptName, String methodName, Object[] args) {
ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);
try {
Class groovyClass = loader.parseClass(new File(scriptName));
groovyObject = (GroovyObject) groovyClass
.newInstance();
return groovyObject.invokeMethod(methodName, args);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
DynamicGroovy dynamicGroovy = new DynamicGroovy();
Object[] params = {new Integer(2)};
Object result = dynamicGroovy.invokeScriptMethod("src/Foo.groovy", "run", params);
System.out.println(result);
System.out.println(dynamicGroovy.getProperty("x"));
}
}

3.动态的载入Groovy脚本

动态载入脚本就更简单了,因为Groovy提供了一个方法evaluate,,和javascript的eval很像吧:

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

public class TestEval {

public Object doit() {
Binding bb = new Binding();
bb.setVariable("test", "hello world!");
GroovyShell gs = new GroovyShell(bb);
return gs.evaluate("println test");
}

/**

  • @param args
    */
    public static void main(String[] args) {
    TestEval te = new TestEval();
    te.doit();

}

}

简单吧,通过evaluate一个字符串就行了,evaluate还支持脚本文件和类文件哦….功能很强大的.

  • Groovy与流行框架的集成

1.与Spring的集成

现在Spring的核心包就提供了与Groovy的集成了,,很好,很强大,这样就可以显示业务逻辑的动态改变了

由于Groovy的代码中也有描述Java代码的机制,因此两者合用非常容易
Spring Bean:

代码
class="org.springframework.beans.factory.groovy.GroovyFactory">
20

下面是groovy的例子:

代码
factory-bean="groovyScriptFactory"
factory-method="create">

SimpleHello.groovy

groovy文件:

代码
package org.springframework.beans.factory.groovy;

class Test implements Hello {

String sayHello() {
"hello world"
}
}

2.与webwork的集成

在WebWork2中,可以使用Groovy实
现Action类来简化代码,提高编码效率

例子:

package web

import java.util.Date

import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory

import com.opensymphony.xwork.ActionSupport

class GroovyAction extends ActionSupport {

protected final Log logger = LogFactory.getLog(getClass())

private String now

String execute() {
now = "${new Date()}"
logger.info("returning view with ${now}")

"success"
}

void setNow(String now) {
this.now = now
}

String getNow() {
now
}

}
上面的Action类是Groovy类,同样扩展ActionSupport,这里要注意:

execute()方法没有throws Exception语句,这是因为目前的Groovy还没有这个Java特性,这需要在以后的版本中增加;如果添加,编译会报错

execute()方法返回时,不要使用类似SUCCESS的常量,而是用对应的值(如"success");如果使用SUCCESS,Groovy会把它解析成类的属性,抛异常

当然,在/WEB-INF/lib目录下需要包含运行以依赖的jar文件:Groovy和ASM.

在我的笔记本上装了Intellij IDEA 7.0 结果启动不了

抛出了ERROR - llij.ide.plugins.PluginManager - java.lang.IllegalArgumentException: Missing extension point: com.intellij.errorHandler in area null

一开始怎么都找不出原因,后来想到了DB4O manager 当时也启动不了是因为开了ClearType的原因

记得加上-Dawt.useSystemAAFontSettings=lcd这个参数就解决了,果然在idea.exe.vmoptions上加上

-Dawt.useSystemAAFontSettings=lcd之后idea启动了

DB4O的Filter如下,是用SODA实现的,,NQ不是太适合做这个

/*
 
DB4O 的 Filter
 
 
@author Kevin.Huang
  @date 2007-9-29
 
/
public class DB4OFilter extends Filter {

 /*
 
DB4o的SODA查询接口
  */
 private Query query;

 /*
 
@param persistentClass
              the persistentClass to set
 
/
 public void setPersistentClass(Class< ? extends Base > persistentClass) {
  query.constrain(persistentClass);
 }

 @Override
 public void addBetween(String field, Object low, Object high) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(low).not().smaller().and(fieldQuery.constrain(high).not().greater());
 }

 @Override
 public void addEqualTo(String field, Object value) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(value);

 }

 @Override
 public void addGreaterOrEqualThan(String field, Object value) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(value).not().smaller();

 }

 @Override
 public void addGreaterThan(String field, Object value) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(value).greater();

 }

 @Override
 public void addIn(String field, Collection< Object > value) {
  Query fieldQuery = query.descend(field);
  if (value != null && !value.isEmpty()) {
   boolean started = false;
   Constraint c = null;
   for (Object o : value) {
    if (!started) {
     c = fieldQuery.constrain(o);
     started = true;
    } else {
     c = orCollection(fieldQuery, c, o);
    }
   }
  } else {
   fieldQuery.constrain(null);
  }
 }

 private Constraint orCollection(Query q, Constraint c, Object o) {
  return c.or(q.constrain(o));
 }

 @Override
 public void addIsNull(String field) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(null);
 }

 @Override
 public void addLessOrEqualThan(String field, Object value) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(value).not().greater();

 }

 @Override
 public void addLessThan(String field, Object value) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(value).smaller();

 }

 @Override
 public void addLike(String field, String value) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(value).like();

 }

 @Override
 public void addNotBetween(String field, Object low, Object high) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(low).smaller().and(fieldQuery.constrain(high).greater());
 }

 @Override
 public void addNotEqualTo(String field, Object value) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(value).not();

 }

 @Override
 public void addNotIn(String field, Collection< Object > value) {
  Query fieldQuery = query.descend(field);
  if (value != null && !value.isEmpty()) {
   boolean started = false;
   Constraint c = null;
   for (Object o : value) {
    if (!started) {
     c = fieldQuery.constrain(o);
     started = true;
    } else {
     c = orCollection(fieldQuery, c, o);
    }
   }
   c.not();
  } else {
   fieldQuery.constrain(null).not();
  }
 }

 @Override
 public void addNotLike(String field, String value) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(value).not().like();

 }

 @Override
 public void addNotNull(String field) {
  Query fieldQuery = query.descend(field);
  fieldQuery.constrain(null).not();
 }

 @Override
 public void addPureLike(String field, String value) {
  addLike(field, value);

 }

 @Override
 public void addPureNotLike(String field, String value) {
  addNotLike(field, value);

 }

 /*
 
@return the query
  */
 public Query getQuery() {
  return query;
 }

 /*
 
@param query
              the query to set
 
/
 public void setQuery(Query query) {
  this.query = query;
 }

用法如下:

public static void main(String[] args) {
  ObjectContainer db = null;
  db = Db4o.openFile("data/persons.data");

  Person kevin = new Person();
  kevin.setName("Kevin");
  kevin.setAge(26);

  Person vivan = new Person();
  vivan.setName("Alex");
  vivan.setAge(28);

  Person John = new Person();
  John.setName("John");
  John.setAge(30);

  db.set(kevin);
  db.set(vivan);
  db.set(John);
  db.commit();

  DB4OFilter f = new DB4OFilter();
  f.setQuery(db.query());//注入query
  f.setPersistentClass(Person.class);//注入要查询的类
  f.addEqualTo("name", "Kevin");
  f.addEqualTo("age", 28);
  ObjectSet< Person > list = f.getQuery().execute();//开始查询
  for (Person p : list) {
   System.out.println(p.getName());
   db.delete(p);
  }
  db.commit();
  db.close();
 }

最近在写自己的框架,由于框架不是很稳定,有较多的重构,用RDBMS的话,重构数据库就能把我搞死..所以选择OODBMS ,

OODBMS用起来还是不错的,可惜没有如Spring等事务管理措施的辅助,处理起事务来还是比较吃力.

既然Spring帮不了我,那就只有自己帮自己了,做事务处理现在流行用AOP来做..对于Spring AOP这种用动态代理机制来模拟AOP

感觉不是很爽,所以一下子就选择AspectJ作为自己的AOP框架,

www.eclipse.org/adjt下载了AspectJ的IDE之后,AspectJ之旅就开始了.

学着例子,自己摆弄了一个aj先:

被AOP的代码:

/*
 
@author Kevin.Huang
  @date 2007-9-27
 
/
public class Test {

 /*
 
@param args
  */
 public static void main(String[] args) {
  sayHello();

 }

 public static void sayHello() {
  System.out.println("Hello");
 }}


AspectJ的代码

/*
 
@author Kevin.Huang
  @date 2007-9-27
 
/
public aspect World {

 pointcut greeting():execution(* Test.sayHello(..));

 after() returning() : greeting() {
  System.out.println(" World!");
 }

}

这是Eclipse的AspectJ插件上展示的例子,很简单.这个时候运行Test,就会打出Hello World!..World!就是通过AOP加上去的,反编译源代码发现实际上AspectJ就是在Test.class上再加上自己的字节码来实现AOP.所以一定程度上也破坏了封装性,但能跑起来,管他呢.

现在来看看AspectJ特有的一下语法:

pointcut  :定义了从joinPoint运行的函数,

execution:定义了AOP运用的范围,有* .. 等通配符可以使用,所以一个aj文件可以为多个同类的方法提供AOP服务

after,before,around,这些就是指定pointcut  从那里开始运行了..

after 后面还可以跟return,throw来判断返回的类型,这个可是写事务管理很重要的特性了..

我这里就简单说说,说太多还怕误人子弟..hoho,自己才刚开始用..

下面就给大家看看我用AspectJ怎么做了一个事务管理的:

被管理的DAO(我用的是db4o作为数据库..hoho):

public class DB4ODAO implements IGenericDAO {

 /*
 

  */
 protected Class< ? extends Base > persistentClass;

 /*
 
@return the persistentClass
  */
 public Class< ? extends Base > getPersistentClass() {
  return persistentClass;
 }

 /*
 
@param persistentClass
              the persistentClass to set
 
/
 public void setPersistentClass(Class< ? extends Base > persistentClass) {
  this.persistentClass = persistentClass;
 }

 /*
 
db4o的session
  */
 protected ObjectContainer db;

 public void delete(Base entity) {
  db.delete(entity);
 }

 public List< ? extends Base > findAll() {
  return db.query(getPersistentClass());
 }

 public < K extends Base> List< K > findByExample(K exampleInstance) {
  return db.get(exampleInstance);
 }

 public < K extends Base> List< K > findByFilter(Filter filter) {
  // TODO Auto-generated method stub
  return null;
 }

 public < K extends Base> K findById(Serializable id) {
  Base obj = null;
  try {
   obj = getPersistentClass().newInstance();
  } catch (InstantiationException e) {
   // XXX 记录异常
   throw new RuntimeException("Domain Model is ERROR!", e);
  } catch (IllegalAccessException e) {
   // XXX 记录异常
   throw new RuntimeException("Domain Model is ERROR!", e);
  }
  obj.setUuid((String) id);
  ObjectSet< K > result = db.get(obj);
  if (result.hasNext()) {
   return result.next();
  } else {
   return null;
  }
 }

 public Integer findCountByFilter(Filter filter) {
  // TODO Auto-generated method stub
  return null;
 }

 public < K extends Base> K saveAndUpdate(K entity) {
  Base obj = findById(entity.getUuid());
  if (obj != null) {
   db.ext().bind(entity, db.ext().getID(obj));
  }
  db.set(entity);
  return entity;
 }

 public ObjectContainer getDb() {
  return db;
 }

 public void setDb(ObjectContainer db) {
  this.db = db;
 }}

里面的find,save,delete等都需要做事务管理

下面就是针对这个DAO的一个aj:

public aspect TransactionDAOAOP {
 private static final Logger LOGGER = Logger.getLogger(TransactionDAOAOP.class);

 private ObjectContainer db;

 private Object joinPoint;

 pointcut readOnly(DB4ODAO dao):execution( DB4ODAO.find*(..))&&this(dao);

 pointcut update(DB4ODAO dao):execution( DB4ODAO.save*(..))&&this(dao);

 pointcut delete(DB4ODAO dao):execution( DB4ODAO.delete(..))&&this(dao);

 before(DB4ODAO dao) :  readOnly(dao) {
  start(dao, thisJoinPoint);
 }

 after(DB4ODAO dao) returning()  :  readOnly(dao) {
  if (joinPoint.equals(thisJoinPoint)) {
   close();
  }
 }

 after(DB4ODAO dao) throwing():  readOnly(dao) {
  close();
 }

 before(DB4ODAO dao) :  update(dao) {
  if (LOGGER.isDebugEnabled()) {
   LOGGER.debug("before updata @" + dao.toString());
  }
  start(dao, thisJoinPoint);
 }

 after(DB4ODAO dao) returning()  :  update(dao) {
  if (joinPoint.equals(thisJoinPoint)) {
   commit();
   close();
  }
 }

 after(DB4ODAO dao) throwing():  update(dao) {
  rollback();
  close();
 }

 before(DB4ODAO dao) :  delete(dao) {
  start(dao, thisJoinPoint);
 }

 after(DB4ODAO dao) returning()  :  delete(dao) {
  if (joinPoint.equals(thisJoinPoint)) {
   commit();
   close();
  }
 }

 after(DB4ODAO dao) throwin
g():  delete(dao) {
  rollback();
  close();
 }

 private void start(DB4ODAO dao, Object thisPoint) {
  if (LOGGER.isDebugEnabled()) {
   LOGGER.debug("db is closed? @" + isClose(dao));
  }
  if (isClose(dao)) {
   db = Db4o.openFile(DB4OConfig.getDataPath());
   dao.setDb(db);
   joinPoint = thisPoint;
  }
 }

 private void commit() {
  db.commit();
 }

 private void rollback() {
  db.rollback();
 }

 private void close() {
  db.close();
 }

 private boolean isClose(DB4ODAO dao) {
  if (dao.getDb() == null) {
   return true;
  } else {
   return dao.getDb().ext().isClosed();
  }
 }

}

这样一来就为DAO做了AOP了

基本的思想就是

开始方法前.先判断Session是否开启,如果没有则开启,并作记录是这个方法开启的Session

然后再运行中如果有其他的AOP的方法插入,这时Session已开启就不用在开启,最后运行到开始记录的方法结束之后就commit再close

如果当中遇到异常则直接rollback并close

记录方法的方法是 joinPoint = thisJoinPoint;

thisJoinPoint是关键字,就是记录了方法开始的点…

Eclipse基于Extension Point的扩展机制果然不同凡响.不用改变源码,通过扩展点添加插件即可实现功能的增强.

先看看如何通过扩展实现功能增强:

我们就看看用户是如何编写一个自己的view,然后扩展org.eclipse.ui.Views来将自己的view在RCP框架中运行起来.

  • 首先要自己实现一个view:

public class View extends ViewPart {

public static final String ID = "com.rcp.test.view.View"; //$NON-NLS-1$

/**

  • Create contents of the view part
  • @param parent
    */
    @Override
    public void createPartControl(Composite parent) {
    Composite container = new Composite(parent, SWT.NONE);
    //
    createActions();
    initializeToolBar();
    initializeMenu();
    }

/**

  • Create the actions
    */
    private void createActions() {
    // Create the actions
    }

/**

  • Initialize the toolbar
    */
    private void initializeToolBar() {
    IToolBarManager toolbarManager = getViewSite().getActionBars().getToolBarManager();
    }

/**

  • Initialize the menu
    */
    private void initializeMenu() {
    IMenuManager menuManager = getViewSite().getActionBars().getMenuManager();
    }

@Override
public void setFocus() {
// Set the focus
}

}

可以看到只要继承了ViewPart 的类就可以进行扩展(因为在Views这个扩展点定义了扩展这个扩展点的时候必须继承ViewPart )

  • 在pulgin.xml中配置扩展信息:

<extension
point="org.eclipse.ui.views">
<view
class="com.rcp.test.view.View"
id="com.rcp.test.view.View"
name="New ViewPart">
</view>
</extension>

很简单在org.eclipse.ui.views下添加这个类就可以了..

大家看到了实现一个扩展,那接下来看看如果定义一个扩展点:

通过Eclipse的图形话工具是很容易就可以定义一个扩展点的.不过我还是说说直接配xml吧(嘿嘿!)

  • 首先在plugin.xml配置一个扩展点:

<extension-point id="ChatListener" name="Chat Listener" schema="schema/ChatListener.exsd"/>

这里只要定义扩展点的id,名字和schema文件,schema就是真正约束扩展点的定义.

  • 定义schema

如上一般schema都是放在schema文件夹下的.来看看schema都包含些什么:

<?xml version='1.0' encoding='UTF-8'?>
<!– Schema file written by PDE –>
<schema targetNamespace="com.kevin.im">
<annotation>
<appInfo>
<meta.schema plugin="com.kevin.im" id="ChatListener" name="Chat Listener"/>
</appInfo>
<documentation>
[文档信息]

</documentation>
</annotation>

<element name="extension">
<complexType>
<sequence minOccurs="2" maxOccurs="2">
<element ref="rosterListener"/>
<element ref="receiver"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>

<element name="rosterListener">
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":org.eclipse.ecf.presence.roster.IRosterListener"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>

<element name="receiver">
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":com.kevin.im.client.IMessageReceiver"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>

<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>

<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>

<annotation>
<appInfo>
<meta.section type="apiInfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>

<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>

<annotation>
<appInfo>
<meta.section type="copyright"/>
</appInfo>
<documentation>

</documentation>
</annotation>

</schema>

如上 <meta.schema plugin="com.kevin.im" id="ChatListener" name="Chat Listener"/>
这句定义了扩展点的plugin id和扩展点的id,在代码中寻找这个扩展点的时候要用 #plugin#.#id#的形式来取..注意:id不能包含".",不然程序会解析不出来

<element name="extension">
<complexType>
<sequence minOccurs="2" maxOccurs="2">
<element ref="rosterListener"/>
<element ref="receiver"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute translatable="true"/&gt
;
</appInfo>
</annotation>
</attribute>
</complexType>
</element>

<element name="rosterListener">
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":org.eclipse.ecf.presence.roster.IRosterListener"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>

<element name="receiver">
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>

</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":com.kevin.im.client.IMessageReceiver"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>

这一段实际上就是XML schema 的定义….这个我这里就不介绍了..直接用可视化编辑很很容易的定义

 

  • 最后看看然后在代码中直接访问这些扩展点:

IExtensionRegistry reg = Platform.getExtensionRegistry();  //从系统中获得扩展点信息
IExtensionPoint extPointForChat = reg.getExtensionPoint("com.test.View");  //根据扩展点id获得整个扩展点

for (IConfigurationElement config : extPointForChat.getConfigurationElements()) {//遍历扩展点的配置

                              View  view=(View) config.createExecutableExtension("class");  //通过class这个attribute来创建这个类
}

//接下去的,就看你用取到的属性干吗了..hoho

 

如果自定义扩展点的信息较多较复杂,则可以模仿*.ui.views读取扩展点信息的方式,分成3种不同的类:

  ● ViewDescriptor——这是一个和自定义扩展点某一项信息相对应的数据类,它实际上为外界封闭了对IConfigurationElement类的访问。

  ● ViewRegistry——如果说ViewDescriptor是扩展点某一项的信息封装,那么ViewRegistry就是对自定义扩展点所有信息的封装。如果把ViewDescriptor比作某个省份,那么ViewRegistry就是整个国家。

  ● ViewRegistryReader——这个类负责向ViewRegistry输送数据,如果说ViewRegistry是盲人,那么ViewRegistryReader就是读报人。