用jBeanBox替换Spring内核实现声明式事务

Spring的问题主要是太复杂、配置方式太多,XML配置不支持运行期修改,不支持IDE类名重构、方法提示。jBeanBox是一个单文件源码只有650行的IOC/AOP微型项目,特点是用JAVA代替XML,简单易懂。目前版本更新到2.0版,添加了AOP联盟和AspectJ接口支持以与其它AOP工具兼容。声明式事务是AOP的典型运用场合,基本原理是利用线程局部变量来管理连接,本想自已写一个简化版的,但一来水平有限,二来AOP的特点就是服务和内核是插拔式设计,内核和服务可以单独使用。Spring中提供的其它业务支持如ORM、JTA、JMS等理论上都可以抽取出来在其它IOC/AOP工具上使用,如果抽取不出来,说明它绑死在Spring内核上了,这与它的设计理念是不符的。本着不重新发明轮子的原则,现试着将Spring中的声明式事务服务抽取出来,与jBeanBox整合,也就是说这一次的整合只利用了Spring的事务服务,而不使用它的IOC/AOP内核,很怪异的组合方式,但目的很明确:取消XML配置。

以下是jBeanBox整合了c3p0数据池+JDBCTemplate+Spring声明式事务的一个例子,实测通过(只有单个文件)。

packageexamples.example3_transaction;

importjava.util.Properties;

importnet.sf.jbeanbox.BeanBox;

importorg.springframework.jdbc.core.JdbcTemplate;

importorg.springframework.jdbc.datasource.DataSourceTransactionManager;

importorg.springframework.transaction.interceptor.TransactionInterceptor;

importcom.mchange.v2.c3p0.ComboPooledDataSource;

classDSPoolBeanBoxextendsBeanBox{

{setClassOrValue(ComboPooledDataSource.class);

setProperty("jdbcUrl","jdbc:mysql://127.0.0.1:3306/test?user=root&password=yourpwd&useUnicode=true&characterEncoding=UTF-8");

setProperty("driverClass","com.mysql.jdbc.Driver");//yourjdbcdrivername

setProperty("maxPoolSize",10);

}

}

classJdbcTmpBoxextendsBeanBox{

{setConstructor(JdbcTemplate.class,newObject[]{newDSPoolBeanBox()});

}

}

classTxManagerBoxextendsBeanBox{

{setClassOrValue(DataSourceTransactionManager.class);

setProperty("dataSource",newDSPoolBeanBox());

}

}

classTxInterceptorBoxextendsBeanBox{//Advice

{Propertiesprops=newProperties();

props.put("insert*","PROPAGATION_REQUIRED");

setConstructor(TransactionInterceptor.class,newObject[]{newTxManagerBox(),props});

}

}

publicclassSpringTxTest{

static{//AOPsetting

BeanBox.setAOPAround("examples.example3_transaction.SpringTx\\w*","insert\\w*",newTxInterceptorBox(),"invoke");

}

publicvoidinsertUser(){

JdbcTemplatedao=newJdbcTmpBox().getBean();

dao.execute("insertintousersvalues('User1')");

inti=1/0;//throwRuntimeException

dao.execute("insertintousersvalues('User2')");

}

publicstaticvoidmain(String[]args){

SpringTxTesttester=newBeanBox(SpringTxTest.class).getBean();

tester.insertUser();

}

}

可以看到,insertUser方法中出错事务将整体回滚,Spring的声明服务生效了。XML彻底消失,配置可以写在Java里随用随配,非常方便。

顺便提一下,从Spring3.0起自带一种基于JAVA的配置,但需要与注解配合使用,复杂难用,而且有以下问题:配置不能继承,运行期不能改配置,以方法名而不是类名来作为bean的缺省ID,目标类重构时,方法名不能跟着自动变更,必须手工更改,这就抵消了重构的意义。

如需运行此例,请修改实际数据库连接及下载下面提到的12个jar包。或是从jBeanBox项目网站下载打包好的"Demo_jBeanBox2.0.war"文件,其中已包含此示例及所有库。

jBeanBox2.0所须包:

http://central.maven.org/maven2/aopalliance/aopalliance/1.0/aopalliance-1.0.jar

http://central.maven.org/maven2/asm/asm/3.3.1/asm-3.3.1.jar

http://central.maven.org/maven2/org/aspectj/aspectjrt/1.8.9/aspectjrt-1.8.9.jar

http://central.maven.org/maven2/cglib/cglib/2.2.2/cglib-2.2.2.jar

此示例所须包:

http://central.maven.org/maven2/c3p0/c3p0/0.9.1.2/c3p0-0.9.1.2.jar

http://central.maven.org/maven2/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar

http://central.maven.org/maven2/mysql/mysql-connector-java/5.1.5/mysql-connector-java-5.1.5.jar

http://central.maven.org/maven2/org/springframework/spring-aop/3.2.16.RELEASE/spring-aop-3.2.16.RELEASE.jar

http://central.maven.org/maven2/org/springframework/spring-beans/3.2.16.RELEASE/spring-beans-3.2.16.RELEASE.jar

http://central.maven.org/maven2/org/springframework/spring-core/3.2.16.RELEASE/spring-core-3.2.16.RELEASE.jar

http://central.maven.org/maven2/org/springframework/spring-jdbc/3.2.16.RELEASE/spring-jdbc-3.2.16.RELEASE.jar

http://central.maven.org/maven2/org/springframework/spring-tx/3.2.16.RELEASE/spring-tx-3.2.16.RELEASE.jar

以上包如需用Maven下载,可在项目主页找到"pom.xml"。

jBeanBox可在githubjBeanBox项目主页下载,就一个文件:

https://github.com/drinkjava2/jBeanBox/blob/master/jBeanBox2.0/BeanBox.java

相关推荐