(一)https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247485265&idx=1&sn=0ea1fe4257cb963d24829f69bb6a32da&chksm=ebd6387ddca1b16b87f12f50b24b239bed93e0e49f243ec560e2c83156ff5ceefe0a2b2e96fc&mpshare=1&scene=1&srcid=0427wPQP4tYUBtlGH5l1JR9i&key=c44bed40495664a4adac9e43d1f05551d8a4f754cb59ce155cd03562861b122f33144ac9d8403e70841b6302eb1f140b592c78f18e0454b0ee34a2ca8276efd12dbd8e67c6c51b455a6ebd0250532b8e&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=zTFOqug6RXGHRQVhLFV5xM2VvZe0nSmsXV1%2Fys3HrXZVPSKfgf3TVZ7FuYVWc0LA
1. 静态代理
public class UserDaoProxy implements IUserDao {
private IUserDao target;
public UserDaoProxy(IUserDao target){
this.target = target;
}
@Override
public void save() {
System.out.println("开始事务static");
target.save();//执行目标对象的方法
System.out.println("提交事务static");
}
}
2. 动态代理
public class ProxyFactory implements InvocationHandler {
//维护一个目标对象
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始事务jdk");
Object returnValue = method.invoke(target, args);
System.out.println("提交事务jdk");
return returnValue;
}
//给目标对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
// 目标对象
IUserDao target = new UserDao();
// 给目标对象,创建代理对象
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
// 执行方法 【代理对象】
proxy.save();
}
3. cglib
public class ProxyFactory implements MethodInterceptor {
//维护目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("开始事务cglib");
//执行目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务cglib");
return returnValue;
}
}
与jdk相同,
一个被代理对象,一个invoke改写埋点,一个创建代理对象
//目标对象
UserDao target = new UserDao();
//代理对象
UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法
proxy.save();
Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
如何强制使用CGLIB实现AOP?
(1)添加CGLIB库,SPRING_HOME/cglib/*.jar
(2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
JDK动态代理和CGLIB字节码生成的区别?
(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
* 实现InvocationHandler
* 使用Proxy.newProxyInstance产生代理对象
* 被代理的对象必须要实现接口
使用JDK动态代理,目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。
CGLib 必须依赖于CGLib的类库,Cglib原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为final类型。针对接口编程的环境下推荐使用JDK的代理。从执行效率上看,Cglib动态代理效率较高。在Hibernate中的拦截器其实现考虑到不需要其他接口的条件Hibernate中的相关代理采用的是CGLib来执行。
个人总结:
jdk方式,实现InvocationHandler接口,使用Proxy,基于反射、动态编译 为实现某接口的类创建代理类
cglib方式,基于字节码,生成子类改写方法,方法不能为final
此外有一个2层jdk动态代理例子:
http://www.cnblogs.com/jiangyi-uestc/p/5755133.html
JDK的代理方式主要就是通过反射跟动态编译来实现的,主要搭配InvocationHandler和Proxy来实现,下面的例子中使用了两层代理(即代理上加了一层代理)。
二、实例
1. 公共接口
1 package com.tgb.proxy; 2 3 public interface UserMgr { 4 5 void addUser(); 6 void delUser(); 7 8 }
2. 实现类
1 package com.tgb.proxy; 2 3 public class UserMgrImpl implements UserMgr { 4 5 @Override 6 public void addUser() { 7 System.out.println("添加用户...."); 8 } 9 10 @Override 11 public void delUser() { 12 System.out.println("删除用户....."); 13 } 14 15 }
3. TransactionHandler(InvocationHandler的实现)
1 package com.tgb.proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class TransactionHandler implements InvocationHandler { 7 8 private Object target; 9 10 public TransactionHandler(Object target){ 11 super(); 12 this.target = target; 13 } 14 15 @Override 16 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 17 18 System.out.println("开启事务..."); 19 20 method.invoke(target); 21 22 System.out.println("提交事务..."); 23 24 return null; 25 } 26 27 28 }
4. TimeHandler(InvocationHandler的实现)
1 package com.tgb.proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.util.Calendar; 6 7 public class TimeHandler implements InvocationHandler { 8 9 private Object target; 10 11 public TimeHandler(Object target) { 12 super(); 13 this.target = target; 14 } 15 16 @Override 17 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 18 19 Calendar calendar = Calendar.getInstance(); 20 21 System.out.println("start time:" + calendar.get(Calendar.HOUR_OF_DAY)); 22 23 method.invoke(target); 24 25 System.out.println("end time:" + calendar.get(Calendar.HOUR_OF_DAY)); 26 27 return null; 28 } 29 30 }
5. 测试类
1 package com.tgb.proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Proxy; 5 6 public class Client { 7 8 public static void main(String[] args) { 9 10 UserMgr userMgr = new UserMgrImpl(); 11 12 // 1.第一层代理----------通过动态代理,添加事务处理 13 InvocationHandler handler = new TransactionHandler(userMgr); 14 UserMgr userMgrProxy = (UserMgr) Proxy.newProxyInstance(userMgr.getClass().getClassLoader(), 15 userMgr.getClass().getInterfaces(), handler); 16 17 // 2.第二层代理----------通过动态代理,添加时间处理 18 InvocationHandler handler2 = new TimeHandler(userMgrProxy); 19 UserMgr userMgrProxy2 = (UserMgr) Proxy.newProxyInstance(userMgrProxy.getClass().getClassLoader(), 20 userMgrProxy.getClass().getInterfaces(), handler2); 21 22 userMgrProxy2.addUser(); 23 24 System.out.println("========================================"); 25 26 userMgrProxy2.delUser(); 27 28 } 29 }
输出结果:
start time:Tue Aug 09 23:54:54 CST 2016 开启事务... 添加用户.... 提交事务... end time:Tue Aug 09 23:54:54 CST 2016 ======================================== start time:Tue Aug 09 23:54:54 CST 2016 开启事务... 删除用户..... 提交事务... end time:Tue Aug 09 23:54:54 CST 2016