面向切面编程开发事务

一.面向切面编程开发事务
  为了解决重复的代码,提出了面向切面编程开发的概念,
  所谓的面向切面的开发就是针对指定的方法,可以在该方法执行之前或者之后织入一些辅助性得到代码

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 }
原文地址:https://www.cnblogs.com/yslf/p/10732147.html