jdk动态代理和cglib的区别
动态代理只能针对实现了接口的类进行方法的增强,而cglib可以针对实现了接口的类或者是没有实现接口的类。
对于没有实现接口的类,cglib对指定的类生成一个子类,然后在子类中重写方法并实现增强的代码。
所以!!!对于用final进行声明的类,用cglib是无法对其进行代理的
1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,
在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
2)在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理,总之,每一次jdk版本升级,jdk代理效率都得到提升,而CGLIB代理消息确有点跟不上步伐。
实现jdk动态代理
我想要实现一个购买商品的功能,但是在购买之前我想确认我是否够钱去购买这件商品
要代理类的接口,接口中定义了个buy方法
public interface UserManger {
public void buy();
}
要代理的类实现了这个接口
public class UserMangerImpl implements UserManger{
@Override
public void buy() {
System.out.println("用户购买了商品");
}
}
动态代理类,重写了invoke方法实现代码的增强
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler{
private Object target;
public Object newProxy(Object target){
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
checkMoney();
Object ret = method.invoke(target, args);
return ret;
}
public void checkMoney(){
System.out.println("检查是否够钱");
}
}
测试类
class Test{
public static void main(String[] args) {
JdkProxy jdkProxy = new JdkProxy();
UserManger userMange = (UserManger)jdkProxy.newProxy(new UserMangerImpl());
userMange.buy();
}
}
实现cglib动态代理
跟上面相同的例子
cglib代理类,用到了cglib.jar和asm.jar
重写了intercept方法
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private Object target;
public Object creatProxy(Object target){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
Object objProxy = enhancer.create();
return objProxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object obj = null;
if("buy".equals(method.getName())){
checkMoney();
}
obj = method.invoke(target, args);
return obj;
}
public void checkMoney(){
System.out.println("检查是否够钱");
}
}
测试类
class Test{
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
UserManger userMange_1 = (UserManger) cglibProxy.creatProxy(new UserMangerImpl());
userMange_1.buy();
}
}