JavaEE5学习笔记05-EJB之会话Bean(sessionBean)总结-----6
BMT就是Bean自己管理事务,这种方式就是以硬编码的方式在Bean中自己通过JTA接口自己维护事务代码,开始事务、提交事务、回滚事务都需要自己以硬编码的方式来维护,这种方式就是一个优点,灵活,不过EJB规范不建议使用此策略来管理事务,而是采用CMT。
代码如下:
package ejb.sessionBean.impl;
??
/**
?* bean代码自管理事务
?*
?* @author liuyan
?*
?*/
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class BMTServerEAOImpl implements BMTServer {
?
??? private DataSource dataSource;
?
??? @Resource
??? private UserTransaction userTransaction;
?
??? public BMTServerEAOImpl() throws NamingException {
?????? Context context = new InitialContext();
?????? dataSource = (DataSource) context.lookup("java:/jbossdemo");
??? }
?
??? @Override
??? public void insert() throws Exception {
?
?????? Connection connection = null;
?
?????? Statement statement = null;
?
?????? try {
?
?????????? // 开始事务
?????????? userTransaction.begin();
?
?????????? connection = dataSource.getConnection();
?
?????????? statement = connection.createStatement();
?
?????????? String insert1 = "insert into person values(17,'一线生')";
?
?????????? String insert2 = "insert into person values(16,'冷剑白狐')";
?
?????????? statement.executeUpdate(insert1);
?
?????????? statement.executeUpdate(insert2);
?????????? // 事务手工提交
?????????? userTransaction.commit();
?????????? statement.close();
?????????? connection.close();
?????? } catch (Exception e) {
?????????? System.out.println("事务回滚~~");
?????????? userTransaction.rollback();
?????????? e.printStackTrace();
?????? }
??? }
}
测试代码不再赘述,执行后JBoss控制台如下,数据库也没添加任何数据。
15:18:47,568 INFO? [STDOUT] 事务回滚~~
15:18:47,638 ERROR [STDERR] com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '16' for key 'PRIMARY'
把代码稍微修改一下,将重复的主键修改一下
String insert2 = "insert into person values(18,'冷剑白狐')";
执行后数据库成功插入新的纪录,如下
?
EJB也支持简单的自定义AOP类和横切方法,还是直接看例子吧。
AOP类——MyInterceptor
?
package aop;
import java.lang.reflect.Method;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
?
/**
?* 自定义的拦截器
?*
?* @author liuyan
?*
?*/
public class MyInterceptor {
??? @AroundInvoke
??? public Object log(InvocationContext ctx) throws Exception {
?????? System.out.println("日志开启");
?????? Object object = ctx.getTarget();
?????? System.out.println("拦截的SessionBean实例:" + object);
?????? Method method = ctx.getMethod();
?????? System.out.println("拦截的SessionBean方法:" + method.getName());
?????? Object objectReturn = ctx.proceed();
?????? System.out.println("日志记录结束");
?????? return objectReturn;
??? }
}
所谓横切方法,实际上就是代理执行,那么在此AOP类中就需要调用被拦截的方法。Object objectReturn = ctx.proceed();就是执行被拦截目标类的方法。如果没有此行代码,那么目标方法将不会执行。
下面看一下被横切,拦截的目标类——HelloAopServerEAOImpl
?
package aop.server.impl;
import javax.ejb.Stateless;
import javax.interceptor.ExcludeClassInterceptors;
import javax.interceptor.Interceptors;
import aop.MyInterceptor;
import aop.server.HelloAopServer;
?
@Stateless
@Interceptors(MyInterceptor.class)
public class HelloAopServerEAOImpl implements HelloAopServer {
?
??? @Override
??? @ExcludeClassInterceptors
??? public void noAop() {
?????? System.out.println("noAop()");
?
??? }
?
??? @Override
??? public String sayHello() {
?????? return "hello AOP";
??? }
?
??? @Override
??? public void sayWelcome() {
?????? System.out.println("sayWelcome()");
??? }
}
在目标类中使用@Interceptors(MyInterceptor.class)注解代表使用此类被作为AOP的目标所拦截。而此类的方法上加上@ExcludeClassInterceptors注解则代表该方法不会被拦截。
客户端测试代码如下:
?
??? public void test01() throws Exception {
?????? Context context = init();
?????? HelloAopServer helloAopServer = (HelloAopServer) context
????????????? .lookup("HelloAopServerEAOImpl/remote");
?????? helloAopServer.sayHello();
?????? helloAopServer.sayWelcome();
?????? helloAopServer.noAop();
??? }
执行后,服务器控制台信息如下
?
15:40:16,812 INFO? [STDOUT] 日志开启
15:40:16,812 INFO? [STDOUT] 拦截的SessionBean实例:aop.server.impl.HelloAopServerEAOImpl@1dc88c7
15:40:16,812 INFO? [STDOUT] 拦截的SessionBean方法:sayHello
15:40:16,812 INFO? [STDOUT] 日志记录结束
15:40:16,822 INFO? [STDOUT] 日志开启
15:40:16,822 INFO? [STDOUT] 拦截的SessionBean实例:aop.server.impl.HelloAopServerEAOImpl@1dc88c7
15:40:16,822 INFO? [STDOUT] 拦截的SessionBean方法:sayWelcome
15:40:16,822 INFO? [STDOUT] sayWelcome()
15:40:16,822 INFO? [STDOUT] 日志记录结束
15:40:16,831 INFO? [STDOUT] noAop()
可以证明:预期该拦截的sayHello()和sayWelcome()都被拦截了,而noAop()并没有被拦截到。