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动态代理运行结果

在这里插入图片描述

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • J2ME开发步骤

    J2ME开发步骤1.安装JDK2.安装WTK2.5.23.安装MIDP4.Netbeans5.5.15.MobilePack5.5.1部署J2ME您可以从Sun下载一个仿真器,该仿真器允许您在台式机系统上测试J2ME应用程序。如果您宁愿避免所有的图形开销,则您也可以在命令行上部署J2ME。在仿真环境中进行部署在仿真环境中部署和运行J2ME应用程序,要涉及到仿真器的安装和配置。J2

  • ASP.NET和MSSQL高性能分页

    首先是存储过程,只取出我需要的那段数据,如果页数超过数据总数,自动返回最后一页的纪录:setANSI_NULLSONsetQUOTED_IDENTIFIERONGO–===========

    2021年12月20日
  • 无线视频传输技术「建议收藏」

    无线视频传输技术「建议收藏」原文地址:http://www.ed-china.com/ART_8800047847_400002_500018_HN_151edec4.HTMWiDi/Miracast将在无线高清视频传输市场占最大份额据IHSiSuppli公司的显示电子特别报告,在消费与移动产品高清视频无线传输市场,三种基于Wi-Fi的视频技术将胜过两种应用范围较窄的专有技术。今年能传输高清视频

  • 进程和线程的主要区别(总结)

    进程和线程的主要区别(总结)根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调…

  • dfs是什么意思_bmob分页查询

    dfs是什么意思_bmob分页查询给定 n 个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?输入格式第一行是一个正整数 n。第二行是 n 个不大于10000的正整数。输出格式一个正整数,即最少需要的组数。数据范围1≤n≤10输入样例:614 20 33 117 143 175输出样例:3#include<bits/stdc++.h>using namespace std;const int N = 1e2 + 10;int a[N],g[N][N];int n;int

  • WebRTC直播技术方案「建议收藏」

    WebRTC直播技术方案「建议收藏」我们都知道,WebRTC是面向互联网的一种即时通信标准,由于被Chrome、火狐、Safari等主流浏览器支持,并提供了一致和简洁的API,使得开发WebRTC的视频通信应用非常简单和流行。在大多数情况下,我们认为双向视频通信技术和视频直播技术是两种不同的技术,一个做视频通话,一个做单向直播(在以往的直播方案中,绝大部分是采用rtmp协议做直播上行的)。有没有可能使用WebR…

发表回复

您的电子邮箱地址不会被公开。

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