Spring 代理模拟(I)

阅读更多
public interface IUserDAO {
    @Transactional
    String add();
    String query();
}

   

public class UserDAOImpl implements IUserDAO {

    public String add() {
        System.out.println("add ok!");
        return "add";
    }
    public String query() {
        System.out.println("query ok!");
        return "query";
    }
}

 

import org.junit.Test;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Spring事务代理可以分为JDK动态代理和CGLIB代理模式,
 * JDK动态代理是依赖于接口的,
 * java.lang.reflect.Proxy.newProxyInstance方法根据传入的接口类型 (obj.getClass.getInterfaces())动态构造一个代理类实例返回,
 * 这也说明了为什么动态代理实现要求其所代理的对象一定要实现 一个接口。
 * 这个代理类实例在内存中是动态构造的,它实现了传入的接口列表中所包含的所有接口。
 *
 *
 * 就是通过这样一个动态代理对所有需要事务管理的Bean进行加载,并根据配置在invoke方法中对当前调用的 方法名进行判定,
 * 并在method.invoke方法前后为其加上合适的事务管理代码,这样就实现了Spring式的事务管理。
 * Spring中的AOP实 现更为复杂和灵活,不过基本原理是一致的
 * Created by kenny.dong on 2018/4/6.
 */
public class JDKProxyTest {
    @Test
    /**
     * jdk动态代理测试
     */
    public void jdkProxyTest(){
        //01.先创建出接口实现类
        final IUserDAO dao=new UserDAOImpl();
        //02.类Proxy
        IUserDAO proxy=(IUserDAO) Proxy.newProxyInstance(dao.getClass().getClassLoader(), //获取实现类的类加载器
                dao.getClass(). getInterfaces(), // 获取实现类接口
                new InvocationHandler() {  //Invocation(调用 ) Handler (处理)
                            /**proxy  代理对象本身
                             * method 被代理对象 方法  add()
                             * args add方法的参数
                             */
                            public Object invoke(Object proxy, Method method, Object[] args)
                                    throws Throwable {
                                if(method.getAnnotation(Transactional.class) != null){
                                    System.out.println("start Transaction");
                                    //code 1
                                    //真正业务
                                    //执行dao对象的add方法,传入的是args参数,返回值是result
                                    Object result = method.invoke(dao, args);
                                    //code 2
                                    System.out.println("commit Transaction");
                                    return result;
                                }else{
                                    return method.invoke(dao, args);
                                }
                            }
          });
        String add = proxy.add();
        System.out.println("add 方法运行结果" + add);//"add"
        proxy.query();
    }

}

 

 

 

 

你可能感兴趣的:(Spring)