以下是jBeanBox整合了c3p0数据池+JDBCTemplate+Spring声明式事务的一个例子,实测通过。
package examples.example3_transaction;
import java.util.Properties;
import net.sf.jbeanbox.BeanBox;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import com.mchange.v2.c3p0.ComboPooledDataSource;
class DSPoolBeanBox extends BeanBox {
{ 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");//your jdbc driver name
setProperty("maxPoolSize", 10);
}
}
class JdbcTmpBox extends BeanBox {
{ setConstructor(JdbcTemplate.class, new Object[] { new DSPoolBeanBox() });
}
}
class TxManagerBox extends BeanBox {
{ setClassOrValue(DataSourceTransactionManager.class);
setProperty("dataSource", new DSPoolBeanBox());
}
}
class TxInterceptorBox extends BeanBox {// Advice
{ Properties props = new Properties();
props.put("insert*", "PROPAGATION_REQUIRED");
setConstructor(TransactionInterceptor.class, new Object[] { new TxManagerBox(), props });
}
}
public class SpringTxTest {
static {// AOP setting
BeanBox.setAOPAround("examples.example3_transaction.SpringTx\\w*", "insert\\w*", new TxInterceptorBox(), "invoke");
}
public void insertUser() {
JdbcTemplate dao = new JdbcTmpBox().getBean();
dao.execute("insert into users values ('User1')");
int i = 1 / 0; // throw RuntimeException
dao.execute("insert into users values ('User2')");
}
public static void main(String[] args) {
SpringTxTest tester = new BeanBox(SpringTxTest.class).getBean();
tester.insertUser();
}
}
可以看到,insertUser方法中出错事务将整体回滚, Spring的声明服务生效了。讨厌的XML终于彻底消失, 配置和代码的界限模糊,可以在Java里随用随配,程序员又做回了程序员。套用一句话来说:这个世界终于清静了。
顺便提一下, 从Spring3.0起支持一种基于JAVA的配置,但需要与注解配合使用,复杂难用,基本上是一种等同于XML的伪码, 并有以下问题:配置不能继承,运行期不能改配置,以方法名而不是类名来作为bean的缺省ID, 目标类重构时,方法名不能跟着自动变更, 必须手工更改,这就抵消了重构的意义。
例如Spring基于JAVA的配置 :
@Bean
public Student studentBean(){
return new Student("yoona",24);
}
Student student = (Student)context.getBean("studentBean");
当Student类重构为Teacher类时,studentBean这个BeanID不会自动变更为"TeacherBean",必须手工去改。
如需运行本文例子,请修改实际数据库连接及下载下面提到的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
如需用"pom.xml"下载包,可在项目主页找到。
jBeanBox是以源码形式发布,只有一个Java文件,下载页面为:https://github.com/drinkjava2/jBeanBox/tree/master/jBeanBox2.0
以源码形式发布一方面是因为jBeanBox还处于开发期,以源码形式发布便于阅读源码和改错,毕竟是个只有650行源码的小程序。另一主面是因为BeanBox作为IOC/AOP基类,如同一个项目需要存在多套IOC/AOP容器,必须将BeanBox类拷贝并改名以获取新的命名空间。