文章目录

最近在写自己的框架,由于框架不是很稳定,有较多的重构,用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是关键字,就是记录了方法开始的点…

文章目录