cglib动态代理和JDK InvocationHandler动态代理的比较

cglib动态代理和JDK InvocationHandler动态代理的比较
     最近这段时间在学习Spring, 而学习Spring的话,其AOP(Aspect Oritened Programming)面向切面编程又是其核心部分。但是实现AOP的时候我们有两种代理机制:cglib和JDK本身的InvocationHandler代理。
     JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,其实现就需要才cglib.cglib采用了非常底层的字节码技术。原理是:通过字节码技术为一个类创建子类。并且在子类中采用方法拦截的技术拦截所有父类的方法的调用。顺势织入横切逻辑,而jdk与cglib动态代理均是实现spring aop的基础。
     cglib创建的动态代理对象性能比JDK创建性能高很多,但是cglib在创建代理对象的时候所花费时间却是比jdk多的多,所以对于单例的对象,其不需要频繁的创建对象,用cglib更合适,反之,用jdk更好。同时,由于cglib是采用动态创建子类的方法,对于final方法,无法进行代理。
    下面给出两种代理的具体实现代码:
    首先给出cglib代理实现。
    package com.clark.cglib;
/**
 * cglib动态代理  没有接口的类
 * @author Administrator
 *    需要被代理的类,也就是父类
 */
public class SayHello {
    public void say(){
        System.out.println("hello everyone");
    }
}
package com.clark.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
 * 创建子类的方法与代理的方法
 * @author Administrator
 *
 */
public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer=new Enhancer();
    //getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class来创建代理对象
    public Object getProxy(Class clazz){
        //设置需要创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        //通过字节码技术动态创建子类实例
        return enhancer.create();
    }
    /**
     * 实现MethodInterceptor接口方法
     *  intercept()方法拦截所有目标类方法的调用
     *  obj表示目标类的实例,method为目标类方法的反射对象,
     *  为方法的动态入参,proxy为代理类实例。
     *  proxy.invokeSuper(obj, arg2)通过代理类调用父类中的方法
     */
    public Object intercept(Object obj, Method method, Object[] arg2,
            MethodProxy proxy) throws Throwable {
        System.out.println("前置代理");
        //对接入点的放行(Spring aop中接入点)也即实现类方法,要是不掉用此方法,则代理类中的say()方法将不会被执行
        Object result=proxy.invokeSuper(obj, arg2);
        System.out.println("后置代理");
        return null;
    }

}
package com.clark.cglib;

public class CglibTest {
    public static void main(String[] args) {
        CglibProxy proxy=new CglibProxy();
        //创建生成子类的方式创建代理类
        SayHello proxyImpl=(SayHello)proxy.getProxy(SayHello.class);
        proxyImpl.say();
    }
}

一下是JDK的代理实现代码:其主要是要定义一个接口,去定义一些业务方法
package com.clark.jdkInvacation;
/**
 * 目标对象实现的接口,用jdk来生成代理对象一定要实现一个接口
 * @author Administrator
 *
 */
public interface UserService {
    /**
     * 目标方法
     */
    public void add();
}
package com.clark.jdkInvacation;
/**
 * 目标对象
 * @author Administrator
 *
 */
public class UserServiceImpl implements UserService {

    @Override
    public void add() {
        System.out.println("=======add==========");
    }

}
package com.clark.jdkInvacation;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 实现自己的InvocationHandler
 * @author Administrator
 *
 */
public class MyInvocationHandler implements InvocationHandler {
    //目标对象
    private Object target;
    /**
     * 构造方法
     * @param target目标对象
     */
    public MyInvocationHandler(Object target) {
        super();
        this.target = target;
    }
    /**
     * 执行目标对象的方法
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //在目标对象执行之前简单的标记一下
        System.out.println("=====代理前==========");
        //执行目标对象的方法
        Object result=method.invoke(target, args);
        System.out.println("=====代理后==========");
        return result;
    }
    /**
     * 获取目标对象的代理对象
     * @return 代理对象
     */
    public Object getProxy(){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}
package com.clark.jdkInvacation;
/**
 * jdk动态代理测试类
 * @author Administrator
 *
 */
public class ProxyTest {
    public static void main(String[] args) {
        //实例化目标对象
        UserService userService=new UserServiceImpl();
        //实例化InvocationHandler
        MyInvocationHandler invocationHandler=new MyInvocationHandler(userService);
        //根据目标对象生成代理对象
        UserService proxy=(UserService)invocationHandler.getProxy();
        //调用代理对象的方法
        proxy.add();
    }
}







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值