一.面向切面编程开发事务
为了解决重复的代码,提出了面向切面编程开发的概念,
所谓的面向切面的开发就是针对指定的方法,可以在该方法执行之前或者之后织入一些辅助性得到代码
1.开发出一个事务的注解
1 //指定注解的使用范围 (只能在方法上使用) 2 @Target(ElementType.METHOD) 3 //定义注解的声明周期 (运行时有效) 4 @Retention(RetentionPolicy.RUNTIME) 5 public @interface Transactional { 6 }
2.调整业务层实现类 : 加上自己开发的注解
如果有 "@Transactional" 则进行事务处理,否则就不处理
1 public class EmpServiceImpl implements IEmpService { 2 //需要调用数据层的方法所以需要确定数据层的实现类对象 3 private IEmpDAO empDAO = new EmpDAOImpl(); 4 5 @Override 6 @Transactional 7 public boolean addEmp(Emp vo) throws Exception { 8 return this.empDAO.insert(vo)>0; 9 } 10 @Override 11 @Transactional 12 public boolean removeEmpById(Integer id) throws Exception { 13 return this.empDAO.deleteById(id)>0; 14 } 15 @Override 16 @Transactional 17 public boolean editEmp(Emp vo) throws Exception { 18 return this.empDAO.update(vo)>0; 19 } 20 @Override 21 @Transactional 22 public Emp findEmpById(Integer id) throws Exception { 23 return this.empDAO.selectById(id); 24 } 25 @Override 26 @Transactional 27 public Map<String, Object> findAllSplit(String kw, Integer cp, Integer ls) throws Exception { 28 Map<String,Object> map = new HashMap<String, Object>(); 29 map.put("emplist",this.empDAO.selectSplitAll("%"+kw+"%", cp, ls)); 30 //统计数据量 31 int number = this.empDAO.selectCount(kw); 32 //计算出总的页数 33 //int allPages = number/ls+number%ls==0?0:1; 34 //int allPages = (int)Math.ceil(number/(double)ls)); 35 map.put("count",number); 36 map.put("allPages",(int)Math.ceil(number/(double)ls)); 37 map.put("kw",kw); 38 map.put("cp",cp); 39 map.put("ls",ls); 40 return map; 41 } 42 @Override 43 @Transactional 44 public boolean removeBacth(List<Object> ids) throws Exception { 45 return this.empDAO.deleteBatch(ids)>0; 46 } 47 }
3.定义动态代理类
1 public class ServiceProxy implements InvocationHandler { 2 private Object obj; // 真实主题类对象 3 private Connection conn; 4 5 public ServiceProxy() { 6 } 7 public ServiceProxy(Object obj) { 8 this.obj = obj; 9 } 10 @Override 11 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 12 // 保存方法的返回值 13 Object result = null; 14 // 取得业务层实现类对象 (被代理的对象) 正在被执行的方法 15 Method m = this.obj.getClass().getMethod(method.getName(), method.getParameterTypes()); 16 // 读取正在执行的方法上的注解 17 Transactional transactional = m.getDeclaredAnnotation(Transactional.class); 18 System.out.println("注解信息是: " + transactional); 19 // 取得连接 20 if (conn == null) 21 conn = DBUitl.getConnection(); 22 System.out.println("取得连接: " + conn); 23 // 取得真实主体类对象 (就是业务层的实现类对象) 的反射对象 24 Class<?> cls = this.obj.getClass(); 25 26 if (transactional == null) { 27 System.out.println("没有事务处理"); 28 // 取得真实主题类对象中的所有属性 (业务层实现类对象中的 dao 层的实现类对象) 29 for (Field fdao : cls.getDeclaredFields()) { 30 // 取消属性的封装 31 fdao.setAccessible(true); 32 // 取得属性的值 33 Object daoObj = fdao.get(this.obj); 34 // 取得业务层实现类中的 dao 层实现类的 conn 属性 (目的是为了其赋值) 35 Field fconn = daoObj.getClass().getDeclaredField("conn"); 36 fconn.setAccessible(true); 37 // 为业务层实现类中的 dao层的实现类对象的 conn 赋值 38 fconn.set(daoObj, conn); 39 } 40 // 执行方法 41 result = method.invoke(this.obj, args); 42 // 关闭连接 43 DBUitl.close(conn); 44 } else { 45 System.out.println("有事务处理"); 46 try { 47 // 取消事务的自动提交 48 conn.setAutoCommit(false); 49 // 取得真实主题类中的所有属性 50 for (Field fdaoimpl : cls.getDeclaredFields()) { 51 // 取消属性的封装 52 fdaoimpl.setAccessible(true); 53 // 取得属性的值 54 Object fdao = fdaoimpl.get(this.obj); 55 // 取得业务层实现类中的 dao 层 实现类的 conn 属性 56 Field fconn = fdao.getClass().getDeclaredField("conn"); 57 fconn.setAccessible(true); 58 // 为业务层实现类中的 dao 层实现类的 conn 属性赋值 59 fconn.set(fdao, conn); 60 } 61 // 执行方法 62 result = method.invoke(this.obj, args); 63 // 提交事务 64 conn.commit(); 65 } catch (Exception e) { 66 conn.rollback(); 67 e.printStackTrace(); 68 } finally { 69 DBUitl.close(conn); 70 } 71 } 72 System.out.println("关闭连接" + conn); 73 return result; 74 } 75 }
4.定义出工厂类
1 public class ServiceFactory { 2 public static Object geiInstance(Class<?> cls) { 3 try { 4 //真实主体类对象 5 Object obj = cls.newInstance(); 6 //取得代理类对象 7 InvocationHandler hander = new ServiceProxy(obj); 8 //取得被代理之后的真实主题类对象 9 Object proxyServiceObj = Proxy.newProxyInstance(hander.getClass().getClassLoader(), obj.getClass().getInterfaces(), hander); 10 return proxyServiceObj; 11 } catch (Exception e) { 12 e.printStackTrace(); 13 } 14 return null; 15 } 16 }
5.测试
1 public class Test { 2 public static void main(String[] args) throws Exception { 3 //取得真实主题对象 4 IEmpService empService = (IEmpService)ServiceFactory.geiInstance(EmpServiceImpl.class); 5 System.out.println(empService.findAllSplit("A", 1, 10)); 6 } 7 }