使用动态代理简单模拟一下spring的事务管理

按照平时写代码的习惯,我们会定义一个service接口

package com.proxy.test;
public interface UserService {
    public void sayHello(String word);
}

接着是实现类

package com.proxy.test;
public class UserServiceImpl implements UserService{
    @Override
    public void sayHello(String word) {
        System.out.println("执行dao的删除操作,添加一个用户:" + word);
        System.out.println("执行dao的删除添加,删除一个用户:" + word);
    }
}

我们的目的是,执行sayHello中的添加删除操作时,让这几条sql语句同时提交(commit)或同时回滚(rollback),下面我们用动态代理的方式,实现这个功能:
自定义一个代理管家,帮我们创建代理类,需要实现InvocationHandler接口(必须)

package com.proxy.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyProxyManager implements InvocationHandler {
    private Object target;
    public Object bind(Object target){
        this.target = target;
        /*
         * Proxy.newProxyInstance 会返回一个代理对象
         * target.getClass() --> 被代理对象的ClassLoader,这里实际对应UserServiceImpl类
         * target.getClass().getInterfaces() --> 被代理对象实现的接口列表(UserService),指定之后,代理对象就可以使用其接口中的方法了
         * this -- 表示的是当这个动态代理对象在调用方法的时候,会通过哪个InvocationHandler,这里实际是MyProxyManager这个类
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * 我们通过MyProxyManager创建出来的代理对象在调用自己的方法时,
     * 会通过invoke这个方法进行调用,而不是直接调用
     * @param proxy 被代理对象
     * @param method 被代理对象执行的方法
     * @param args 被代理对象执行的方法所需要的参数
     *
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        System.out.println("我是动态代理对象");
        System.out.println("准备进入事务..");
        Object result = null;
        try{
            // 执行被代理对象自己的方法
            result = method.invoke(target, args);
        }catch(Exception e){
            // 如果有错误,执行数据库的rollBack方法
            System.out.println("执行rollBack");
        }
        // 如果没错,执行数据库的commit方法
        System.out.println("执行commit");
        System.out.println("-----------------------");
        return result;
    }
}

测试代码

public static void main(String[] args) {
    MyProxyManager manager = new MyProxyManager();
    // 创建UserService的代理对象
    UserService userService = (UserService) manager.bind(new UserServiceImpl());
    userService.sayHello("lalala");
}

运行看一下效果:

我是动态代理对象
准备进入事务..
执行dao的删除操作,添加一个用户:lalala
执行dao的删除添加,删除一个用户:lalala
执行commit

这里只是使用打印语句简单模拟了数据库的操作,没有真正连接数据库操作,有空的童鞋可以实际操作一下。

我们平时用到的spring的事务管理、springmvc的interceptor都是aop的实例
spring把事务操作放到了代理类中统一commit或rollback
interceptor本身就是一个代理类,在调用指定方法前后添加一系列操作

    原文作者:瓦力
    原文地址: https://segmentfault.com/a/1190000015736004
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞