JDK动态代理和CGLIB代理的区别

一、原理区别:

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 
2、如果目标对象实现了接口,可以强制使用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

二、代码实现

    package com.fy.spring.proxy;    

    public interface UserManager {
        public void addUser(String id, String password);
        public void delUser(String id);
    }   

[html] view plain copy

    package com.fy.spring.proxy;    

    public class UserManagerImpl implements UserManager {    

        public void addUser(String id, String password) {
            System.out.println(".: 掉用了UserManagerImpl.addUser()方法! ");    

        }    

        public void delUser(String id) {
            System.out.println(".: 掉用了UserManagerImpl.delUser()方法! ");    

        }
    }

JDK动态代理类

    package com.fy.spring.proxy;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    /**
     *
     * JDK动态代理类
     *
     *
     */
    public class JDKProxy implements InvocationHandler {    

        private Object targetObject;//需要代理的目标对象    

        public Object newProxy(Object targetObject) {//将目标对象传入进行代理
            this.targetObject = targetObject;
            return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                    targetObject.getClass().getInterfaces(), this);//返回代理对象
        }    

        public Object invoke(Object proxy, Method method, Object[] args)//invoke方法
                throws Throwable {
            checkPopedom();//一般我们进行逻辑处理的函数比如这个地方是模拟检查权限
            Object ret = null;      // 设置方法的返回值
            ret  = method.invoke(targetObject, args);       //调用invoke方法,ret存储该方法的返回值
            return ret;
        }    

        private void checkPopedom() {//模拟检查权限的例子
            System.out.println(".:检查权限  checkPopedom()!");
        }
    }

CGLIBProxy动态代理类

    package com.fy.spring.proxy;    

    import java.lang.reflect.Method;    

    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;    

    /**
     * CGLibProxy动态代理类的实例
     *
     *
     */
    public class CGLibProxy implements MethodInterceptor {    

        private Object targetObject;// CGLib需要代理的目标对象    

        public Object createProxyObject(Object obj) {
            this.targetObject = obj;
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(obj.getClass());
            enhancer.setCallback(this);
            Object proxyObj = enhancer.create();
            return proxyObj;// 返回代理对象
        }    

        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            Object obj = null;
            if ("addUser".equals(method.getName())) {// 过滤方法
                checkPopedom();// 检查权限
            }
            obj = method.invoke(targetObject, args);
            return obj;
        }    

        private void checkPopedom() {
            System.out.println(".:检查权限  checkPopedom()!");
        }
    }

测试类

    public class Client {    

        public static void main(String[] args) {    

            UserManager userManager = (UserManager) new CGLibProxy()
                    .createProxyObject(new UserManagerImpl());
            System.out.println("-----------CGLibProxy-------------");
            userManager.addUser("tom", "root");
            System.out.println("-----------JDKProxy-------------");
            JDKProxy jdkPrpxy = new JDKProxy();
            UserManager userManagerJDK = (UserManager) jdkPrpxy
                    .newProxy(new UserManagerImpl());
            userManagerJDK.addUser("tom", "root");
        }    

    }

运行结果

    -----------CGLibProxy-------------
    检查权限  checkPopedom()!
    掉用了UserManagerImpl.addUser()方法!
    -----------JDKProxy-------------
    检查权限  checkPopedom()!
    掉用了UserManagerImpl.addUser()方法!
JDK代理是不需要以来第三方的库,只要要JDK环境就可以进行代理,它有几个要求
* 实现InvocationHandler
* 使用Proxy.newProxyInstance产生代理对象
* 被代理的对象必须要实现接口
CGLib 必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承但是针对接口编程的环境下推荐使用JDK的代理
在Hibernate中的拦截器其实现考虑到不需要其他接口的条件Hibernate中的相关代理采用的是CGLib来执行。
时间: 2024-10-04 02:48:14

JDK动态代理和CGLIB代理的区别的相关文章

动态代理:JDK动态代理和CGLIB代理的区别

代理模式:代理类和被代理类实现共同的接口(或继承),代理类中存有指向被代理类的索引,实际执行时通过调用代理类的方法.实际执行的是被代理类的方法. 而AOP,是通过动态代理实现的. 一.简单来说: JDK动态代理只能对实现了接口的类生成代理,而不能针对类 CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承) 二.Spring在选择用JDK还是CGLiB的依据: (1)当Bean实现接口时,Spring就会用JDK的动态代理 (2)当Bean没有实现接口时,Spring使

设计模式---JDK动态代理和CGLIB代理

Cglig代理设计模式 /*测试类*/ package cglibProxy; import org.junit.Test; public class TestCglib { @Test public void test1(){ CglibProxy cglibProxy=new CglibProxy(); UserServiceImpl userServiceImpl = (UserServiceImpl)cglibProxy.createProxyInstance(new UserServi

jdk动态代理和cglib代理总结

首先我们来谈谈jdk的动态代理,它允许开发者在运行期创建接口的代理实例,那么当我们在运行过程中调用某个实例的某个方法时,可以使用代理对象去具体实现它,从而达到aop的效果. (1)jdk的动态代理主要涉及两个类:proxy和invocacationHandler,invocationHandler里面包含了横切逻辑,并且可以使用反射调用目标类的方法(就是切点),proxy类主要是使用它的一个newinstance方法去创建一个代理实例. 下面我们来看代码: package com.yue.tes

基于Spring AOP的JDK动态代理和CGLIB代理

一.AOP的概念  在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 二.主要用途 将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务

JDK动态代理和cglib代理

写一个简单的测试用例,Pig实现了Shout接口 public class MyInvocation implements InvocationHandler { Object k; public MyInvocation(Object k) { this.k = k; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //System.out.print

jdk动态代理和cglib动态代理的区别

CGLIB代理: CGLIB底层:使用字节码处理框架ASM,来转换字节码并生成新的类. CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的. 如果目标对象实现了接口,可以强制使用CGLIB实现代理. 如果目标对象没有实现接口,则默认会采用CGLIB代理: 为什么jdk动态代理必须基于接口 原因如下: 1.生成的代理类继承了Proxy,由于java是单继承,所以只能实现接口,通过接口

JDK动态代理和CGLIB的区别

Aspect默认情况下不用实现接口,但对于目标对象,在默认情况下必须实现接口 如果没有实现接口必须引入CGLIB库 我们可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动传入,从JoinPoint中可以取得 参数值.方法名等等 1.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2.如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3.如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

JDK动态代理和CGLIB动态代理

转载自http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html 静态代理 静态代理相对来说比较简单,无非就是聚合+多态: 参考:设计模式笔记 – Proxy 代理模式 (Design Pattern) 动态代理 我们知道,通过使用代理,可以在被代理的类的方法的前后添加一些处理方

JDK动态代理和CGLIB动态代理+源码下载

在上一篇文章-java代理详解讲解实现机制,一种是继承另外一种是组合,而且通过做实现也证明使用组合的方式更加的灵活.之后提到了代理的两种种类,一种是静态代理,另外一种是动态代理.上一篇文件中着重介绍的是静态代理(相对于动态代理很容易理解).这一片文章就接着介绍动态代理. 动态代理实现的最终效果:通过以一个统一的方式实现对任意的接口/类的代理.相比较静态代理而言,我们可以不用再无限制的增加代理类,不用再写许多重复的代码.很符合面向对象设计原则中的"开闭原则":对修改关闭,对扩展开放. 动