zoukankan      html  css  js  c++  java
  • 业务层面向切面事务开发

    一、动态代理实现事务开发

            在业务层的开发时,每个方法都要先取得连接对象,连接对象使用完毕之后还需要关闭代码,这样的代码是重复累赘的,于是提出了面向切面的编程开发的概念,所谓面向切面的开发就是针对指定的方法,可以 在该方法执行之前或者执行之后织入一些辅助性的代码。那么可以用动态代理实现事务的开发。

    二、反射加注解实现事务开发

      在使用了动态代理实现了为业务层方法取得和关闭连接的操作后,还是没有实现事务的处理,很多时候可能要在业务层的一个方法中实现多张数据表的操作(比如转账业务),此时要么所有的操作都成功要么都失败以保证事务的原子性。这时主需要进行处理:先取消事务的自动 提交,如果所有操作都成功了则提交事务,否则就回滚事务。

    三、工厂设计模式实现事务开发

      在使用了动动态代理实现了面向切面开发,解决了重复的辅助性操作的代码,将一些辅助性的操作交给代理去完成,但是使用了动态代理之后发现了客户调用业务层的代码变得复杂起来,此时可以整合工厂设计模式来解决客户端复杂的调用问题,将对象的实例化过程封装到工厂中,客户端不关注对象的实例化过程。

    最终开发代码如下结构:

    //Transactional.java注解代码
    //指定出注解的使用范围
    @Target(ElementType.METHOD)
    //定义注解的生命周期,运行时有效
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Transactional {
    }
    //service层的接口IEmpService.java代码
    public interface IEmpService {
        /**
         * 实现数据的增加 调用dao层的inset()方法
         * @param vo 包含了要插入的数据的vo对象
         * @return    增加成功返回true 否则返回false
         * @throws Exception 
         */
        public boolean addEmp(Emp vo) throws Exception;
        /**
         * 根据编号删除数据 调用dao层的 deleteById()方法
         * @param id 要删除的数据的编号
         * @return 删除成功返回true 否则返回false
         * @throws Exception 
         */
        public boolean removeEmpById(Integer id) throws Exception;
        /**
         * 修改数据 调用dao层的update()方法
         * @param vo 保存了要修改的数据的vo对象
         * @return 修改成功返回true 否则返回false
         */
        public boolean editEmp(Emp vo) throws Exception;
        /**
         * 根据编号查询数据
         * @param id 要查询的数据的编号
         * @return 有数据返回Emp对象 否则返回null
         */
        public Emp findEmpById(Integer id) throws Exception;
        /**
         * 实现模糊分页查询,调用dao层的方法
         * <li>调用selectSplitAll(),取得是雇员信息的集合</li>
         * <li>调用selectCount(),取得查询到的数据量</li>
         * @param kw 模糊查询的关键字
         * @param cp 当前页
         * @param ls 每页显示的数据量
         * @return 保存雇员集合与数据量的Map对象
         */
        public Map<String, Object> findAllSplit(String kw,Integer cp,Integer ls) throws Exception;
        
    }

    //service层的实现类IEmpServiceImpl.java代码
    public class IEmpServiceImpl implements IEmpService {
        private IEmpDAO empDao = new EmpDAOImpl();
        @Override
        public boolean addEmp(Emp vo) throws Exception {
                return this.empDao.insert(vo)>0;
        }
        @Override
        public boolean removeEmpById(Integer id) throws Exception {
                return this.empDao.deleteById(id)>0;
        }
        @Override
        public boolean editEmp(Emp vo) throws Exception {
                return this.empDao.update(vo)>0;
        }
        @Override
        public Emp findEmpById(Integer id) throws Exception {
                return this.empDao.selectById(id);
        }
        @Override
        @Transactional
        public Map<String, Object> findAllSplit(String kw, Integer cp, Integer ls) throws Exception {
            HashMap<String, Object> map = new HashMap<String, Object>();
                map.put("emplist", this.empDao.selectSplitAll("%"+kw+"%", (cp-1)*ls, ls));
                //统计查询到的数据量
                int number=this.empDao.selectCount(kw);
                //计算出总的页数量 int allPages= number/ls+number%ls== ? 0:1;
                //int allPages=(int)Math.ceil(number/(double)ls);
                map.put("count", number);
                map.put("allPages", (int)Math.ceil(number/(double)ls));
                map.put("kw", kw);
                map.put("cp", cp);
                map.put("ls", ls);
                return map;
        }
    }
    //工厂设计模式类 ServiceFactory.java代码如下
    public class ServiceFactory {
        public static Object getInstance(Class<?> cls) {    
            try {
                //真实主体对象
                Object obj = cls.newInstance();
                //取得代理类对象
                InvocationHandler handler = new ServiceProxy(obj);
                //取得被代理之后的真实主体对象
                Object proxyServiceObj = Proxy.newProxyInstance(handler.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
                return proxyServiceObj;
            } catch (Exception e) {
                e.printStackTrace();
            }    
            return null;
        }
    }
    //业务层的动态代理类ServiceProxy.java代码如下
    public class ServiceProxy implements InvocationHandler {
        private Connection conn;
        private Object obj;//真实主体类对象
        public ServiceProxy() {
            super();
        }
        public ServiceProxy(Object obj) {
            super();
            this.obj = obj;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;// 保存方法的返回值
            // 取得业务层实现类对象即被代理的对象正在被执行的方法
            Method m = this.obj.getClass().getMethod(method.getName(), method.getParameterTypes());
            // 读取正在执行的方法上的注解
            Transactional transactional = m.getDeclaredAnnotation(Transactional.class);
            System.out.println("注解信息是:" + transactional);// 获取注解并打印
            if (conn == null)
                conn = DBUtil.getConnection();
            System.out.println("取得连接:" + conn);
            Class<?> cls = this.obj.getClass();// 取得真实主体对象,就是业务层的实现类对象的反射对象
            try {
                if (transactional == null) {
                    System.out.println("没有事务处理");
                    // 取得真实主体类对象中的所有属性业务层实现类对象中的dao层的实现类对象
                    for (Field fdao : cls.getDeclaredFields()) {
                        fdao.setAccessible(true);// 去除私有封装限制
                        // 取得业务层实现类对象中的属性对象,就是dao层的实现类对象
                        Object daoObj = fdao.get(this.obj);
                        Field fconn = daoObj.getClass().getDeclaredField("conn");
                        // 取得dao层实现类的conn属性目的是为其赋值
                        fconn.setAccessible(true);// 去除私有封装限制
                        fconn.set(daoObj, conn);// 为业务层实现类中的dao实现类的conn属性赋值
                    }
                    result = method.invoke(obj, args);// 执行方法
                } else {
                    System.out.println("有事务处理");
                    conn.setAutoCommit(false);// 取消事务的自动提交
                    for (Field fdao : cls.getDeclaredFields()) {// 取得真实主题类对象中的所有属性
                        fdao.setAccessible(true);// 去除私有封装限制
                        // 取得业务层实现类对象中的属性对象,就是dao层的实现类对象
                        Object daoObj = fdao.get(this.obj);
                        // 取得dao层实现类的conn属性,目的是为其赋值
                        Field fconn = daoObj.getClass().getDeclaredField("conn");
                        fconn.setAccessible(true);// 去除私有封装访问限制
                        fconn.set(daoObj, conn);// 为业务层实现类中的dao实现类的conn属性赋值
                    }
                    result = method.invoke(obj, args);// 调用方法
                    conn.commit();// 手动提交事务
                }
            } catch (Exception e) {
                conn.rollback();// 如果出现问题回滚事务
                e.printStackTrace();//打印出故障问题,但程序还是继续执行
            } finally {
                DBUtil.Close(conn);// 关闭连接
            }
            System.out.println("关闭连接");
            return result;
        }
    }

     改进后的业务层的动态代理类ServiceProxy.java代码如下 ,conn放入invoke(Object proxy, Method method, Object[] args)里面

    //业务层的动态代理类ServiceProxy.java代码如下
    public class ServiceProxy implements InvocationHandler {
    //    private Connection conn;
        private Object obj;// 真实主体类对象
    
        public ServiceProxy() {
            super();
        }
    
        public ServiceProxy(Object obj) {
            super();
            this.obj = obj;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Connection conn=DBUtil.getConnection();
            Object result = null;// 保存方法的返回值
            // 取得业务层实现类对象即被代理的对象正在被执行的方法
            Method m = this.obj.getClass().getMethod(method.getName(), method.getParameterTypes());
            // 读取正在执行的方法上的注解
            Transactional transactional = m.getDeclaredAnnotation(Transactional.class);
            System.out.println("注解信息是:" + transactional);// 获取注解并打印
            if (conn == null)
                conn = DBUtil.getConnection();
            System.out.println("取得连接:" + conn);
            Class<?> cls = this.obj.getClass();// 取得真实主体对象,就是业务层的实现类对象的反射对象
            try {
                if (transactional == null) {
                    System.out.println("没有事务处理");
                    // 取得真实主体类对象中的所有属性业务层实现类对象中的dao层的实现类对象
                    for (Field fdao : cls.getDeclaredFields()) {
                        fdao.setAccessible(true);// 去除私有封装限制
                        // 取得业务层实现类对象中的属性对象,就是dao层的实现类对象
                        Object daoObj = fdao.get(this.obj);
                        Field fconn = daoObj.getClass().getDeclaredField("conn");
                        // 取得dao层实现类的conn属性目的是为其赋值
                        fconn.setAccessible(true);// 去除私有封装限制
                        fconn.set(daoObj, conn);// 为业务层实现类中的dao实现类的conn属性赋值
                    }
                    result = method.invoke(obj, args);// 执行方法
                } else {
                    System.out.println("有事务处理");
                    conn.setAutoCommit(false);// 取消事务的自动提交
                    for (Field fdao : cls.getDeclaredFields()) {// 取得真实主题类对象中的所有属性
                        fdao.setAccessible(true);// 去除私有封装限制
                        // 取得业务层实现类对象中的属性对象,就是dao层的实现类对象
                        Object daoObj = fdao.get(this.obj);
                        // 取得dao层实现类的conn属性,目的是为其赋值
                        Field fconn = daoObj.getClass().getDeclaredField("conn");
                        fconn.setAccessible(true);// 去除私有封装访问限制
                        fconn.set(daoObj, conn);// 为业务层实现类中的dao实现类的conn属性赋值
                    }
                    result = method.invoke(obj, args);// 调用方法
                    conn.commit();// 手动提交事务
                }
            } catch (Exception e) {
                conn.rollback();// 如果出现问题回滚事务
                e.printStackTrace();// 打印出故障问题,但程序还是继续执行
            } finally {
                DBUtil.Close(conn);// 关闭连接
            }
            System.out.println("关闭连接");
            return result;
        }
    }

     

  • 相关阅读:
    蛋疼的j2ee空指针异常
    编译原理 (预处理>编译>汇编>链接)(转)
    自己写的注册表 键值拷贝 函数 RegCopyTree
    十招教你从程序员转向企业家(转)
    pyCharm使用申请的学生免费JetBrains Account登录时失败,弹出"Your host may be behind a proxy..."
    sharepoint:苹果设备访问设置(包括打开infopath表单) 金大昊(jindahao)
    sharepoint:workflow权限代码示例 金大昊(jindahao)
    sharepoint:各种阀值 金大昊(jindahao)
    infopath:部署有代码的表单,任务没有跑 金大昊(jindahao)
    谁在排斥sharepoint 金大昊(jindahao)
  • 原文地址:https://www.cnblogs.com/whymoney1000/p/10732131.html
Copyright © 2011-2022 走看看