Spring的两种动态代理Jdk与Cglib

Spring的两种动态代理Jdk与CglibSpring的两种动态代理Jdk与Cglib

大家好,又见面了,我是你们的朋友全栈君。

一、原理区别:

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

  • 代理类与代理对象的关系?
    jdk动态代理是父子关系:通过反射机制,复刻了一份代理类 。
    cglib动态代理是兄弟关系: 因为代理类继承代理对象,从而实现动态代理。
    Ps:多重代理类要是用cglib去做,jdk会紊乱。
  • 如何强制使用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.lf.shejimoshi.proxy.entity;
//用户管理接口
public interface UserManager { 
   
    //新增用户抽象方法
    void addUser(String userName,String password);
    //删除用户抽象方法
    void delUser(String userName);
    
}

用户管理接口实现类

package com.lf.shejimoshi.proxy.entity;
//用户管理实现类,实现用户管理接口
public class UserManagerImpl implements UserManager{ 
   
    //重写新增用户方法
    @Override
    public void addUser(String userName, String password) { 
   
        System.out.println("调用了新增的方法!");
        System.out.println("传入参数为 userName: "+userName+" password: "+password);
    }
    //重写删除用户方法
    @Override
    public void delUser(String userName) { 
   
        System.out.println("调用了删除的方法!");
        System.out.println("传入参数为 userName: "+userName);
    }
    
}

JDK动态代理

package com.lf.shejimoshi.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.lf.shejimoshi.proxy.entity.UserManager;
import com.lf.shejimoshi.proxy.entity.UserManagerImpl;
//JDK动态代理实现InvocationHandler接口
public class JdkProxy implements InvocationHandler { 
   
    private Object target ;//需要代理的目标对象
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
   
        System.out.println("JDK动态代理,监听开始!");
        Object result = method.invoke(target, args);
        System.out.println("JDK动态代理,监听结束!");
        return result;
    }
    //定义获取代理对象方法
    private Object getJDKProxy(Object targetObject){ 
   
        //为目标对象target赋值
        this.target = targetObject;
        //JDK动态代理只能针对实现了接口的类进行代理,newProxyInstance 函数所需参数就可看出
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
    }
    
    public static void main(String[] args) { 
   
        JdkProxy jdkProxy = new JdkProxy();//实例化JDKProxy对象
        UserManager user = (UserManager) jdkProxy.getJDKProxy(new UserManagerImpl());//获取代理对象
        user.addUser("admin", "123123");//执行新增方法
    }
    
}

JDK动态代理运行结果

在这里插入图片描述Cglib动态代理(需要导入两个jar包,asm-5.2.jar,cglib-3.2.5.jar。版本自行选择)

package com.lf.shejimoshi.proxy.cglib;

import java.lang.reflect.Method;

import com.lf.shejimoshi.proxy.entity.UserManager;
import com.lf.shejimoshi.proxy.entity.UserManagerImpl;

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

//Cglib动态代理,实现MethodInterceptor接口
public class CglibProxy implements MethodInterceptor { 
   
    private Object target;//需要代理的目标对象
    
    //重写拦截方法
    @Override
    public Object intercept(Object obj, Method method, Object[] arr, MethodProxy proxy) throws Throwable { 
   
        System.out.println("Cglib动态代理,监听开始!");
        Object invoke = method.invoke(target, arr);//方法执行,参数:target 目标对象 arr参数数组
        System.out.println("Cglib动态代理,监听结束!");
        return invoke;
    }
    //定义获取代理对象方法
    public Object getCglibProxy(Object objectTarget){ 
   
        //为目标对象target赋值
        this.target = objectTarget;
        Enhancer enhancer = new Enhancer();
        //设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类
        enhancer.setSuperclass(objectTarget.getClass());
        enhancer.setCallback(this);// 设置回调 
        Object result = enhancer.create();//创建并返回代理对象
        return result;
    }
    
    public static void main(String[] args) { 
   
        CglibProxy cglib = new CglibProxy();//实例化CglibProxy对象
        UserManager user =  (UserManager) cglib.getCglibProxy(new UserManagerImpl());//获取代理对象
        user.delUser("admin");//执行删除方法
    }
    
}

Cglib动态代理运行结果

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/106509.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ajax php投票记录功能,PHP 实例 AJAX 投票 | 菜鸟教程[通俗易懂]

    PHP实例-AJAX投票AJAX投票在下面的实例中,我们将演示一个投票程序,通过它,投票结果在网页不进行刷新的情况下被显示。你喜欢PHP和AJAX吗?是:否:实例解释-HTML页面当用户选择上面的某个选项时,会执行名为”getVote()”的函数。该函数由”onclick”事件触发。poll.html文件代码如下:菜鸟教程(runoob.com)function…

    2022年4月12日
  • Cooley-Tukey算法 (蝶形算法)

    Cooley-Tukey算法 (蝶形算法)

    2021年12月2日
  • json文件格式详解

    json文件格式详解  JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition – December 1999的一个子集。 JSON…

    2022年4月8日
  • java dom4j解析xml 对象_Java XML解析 – 利用DOM4j解析XML

    java dom4j解析xml 对象_Java XML解析 – 利用DOM4j解析XMLJavaXML解析-利用DOM4j解析XMLdom4j是一个简单的开源库,用于处理XML、XPath和XSLT,它基于Java平台,使用Java的集合框架,全面集成了DOM,SAX和JAXP。dom4j是目前在xml解析方面是最优秀的(Hibernate、Sun的JAXM也都使用dom4j来解析XML),它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XMLS…

    2022年6月21日
  • Nginx配置——反向代理

    Nginx配置——反向代理Nginx

    2022年7月14日
  • NVIC的使用[通俗易懂]

    NVIC的使用[通俗易懂]NVIC相关内容中断编程的四个部分——1.使能中断请求;2.配置中断优先级分组(一个项目中只需要配置一次)3.配置NVIC寄存器,初始化NVIC_InitTypeDef;4.编写中断服务函数。中断过程的三个部分——1.配置NVIC_Config()函数:NVIC是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。因此控制中断的进行与NVIC_Config函数的配置密切相关。2.配置EXTI_Config()函数:3.编写中断服务函数:…

    2022年5月27日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号