使用動態代理簡單模擬一下spring的事務管理

按照平時寫代碼的習慣,咱們會定義一個service接口java

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

接着是實現類spring

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接口(必須)sql

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");
}

運行看一下效果:mvc

我是動態代理對象
準備進入事務..
執行dao的刪除操做,添加一個用戶:lalala
執行dao的刪除添加,刪除一個用戶:lalala
執行commit

這裏只是使用打印語句簡單模擬了數據庫的操做,沒有真正鏈接數據庫操做,有空的童鞋能夠實際操做一下。ide


咱們平時用到的spring的事務管理、springmvc的interceptor都是aop的實例
spring把事務操做放到了代理類中統一commit或rollback
interceptor自己就是一個代理類,在調用指定方法先後添加一系列操做測試

相關文章
相關標籤/搜索