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