Java 的动态代理如何实现?

news/2024/12/23 6:16:30/

目录

面试回答

知识扩展

静态代理和动态代理的区别

动态代理的用途

Spring AOP 的实现方式

JDK 动态代理的代码段

Cglib 动态代理的代码段


面试回答

在 Java 中,实现动态代理有两种方式:

  1. JDK 动态代理:java.lang.reflect包中的 Proxy 类和 InvocationHandler接口提供了生成动态代理类的能力。
  2. Cglib 动态代理:Cglib(Code Generation Library)是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。

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

JDK 的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用 CGLIB 的实现。

CGLIB 是一个强大的高性能的代码生成包,它可以在运行期扩展 Java 类与实现 Java 接口。它广泛的被许多 AOP 的框架使用,例如 Spring AOPdynaop ,为他们提供方法的 interception (拦截)。

CGLIB 包的底层是通过使用一个小儿快的字节码处理框架 ASM,来转换字节码并生成新的类。不鼓励直接使用 ASM,因为它需要你对 JVM 内部结构包括 class 文件的格式和指令集都很熟悉。

所以,使用 JDK 动态代理的对象必须实现一个或多个接口;而使用 cglib 代理的对象则无需实现接口,达到代理类无侵入。

知识扩展

静态代理和动态代理的区别

最大的区别就是静态代理是编译期确定的,但是动态代理却是运行期确定的。

同时,使用静态代理模式需要程序员手写很多代码,这个过程是比较浪费时间和精力的。一旦需要代理的类中方法比较多,或者需要同时代理多个对象的时候,这无疑会增加很大的复杂度。

反射是动态代理的实现方式之一。

动态代理的用途

Java 的动态代理,在日常开发中可能并不经常使用,但是并不代表他不重要。Java 的动态代理的最主要的用途就是应用在各种框架中。因为使用动态代理可以很方便的运行期生成代理类,通过代理类可以做很多事情,比如 AOP,比如过滤器、拦截器等。

在我们平时使用的框架中,像 servletfilter 、包括 spring提供的 aop以及 struts2的拦截器都使用了动态代理功能。我们日常看到的 mybatis分页插件,以及日志拦截、事务拦截、权限拦截这些几乎全部由动态代理的身影。

Spring AOP 的实现方式

Spring AOP 的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理。

JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类。

如果目标类没有实现接口,那么 Spring AOP会选择使用 CGLIB来动态代理目标类。

CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB做动态代理的。

JDK 动态代理的代码段

public interface UserService {void add();
}
public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("--------------------add----------------------");}
}
public class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target){super();this.target=target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result=method.invoke(target,args);return result;}public Object getProxy(){return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this);}
}
    public static void main(String[] args) throws Exception {UserService service=new UserServiceImpl();MyInvocationHandler handler=new MyInvocationHandler(service);UserService proxy=(UserService) handler.getProxy();proxy.add();}

Cglib 动态代理的代码段

public class CglibProxy implements MethodInterceptor {private Enhancer enhancer=new Enhancer();public Object getProxy(Class clazz){//设置需要创建子类的类enhancer.setSuperclass(clazz);enhancer.setCallback(this);//通过字节码技术动态创建子类实例return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("前置代理");Object result=methodProxy.invokeSuper(o,objects);System.out.println("后置代理");return result;}
}
    public static void main(String[] args) throws Exception {CglibProxy proxy=new CglibProxy();//通过生成子类的方式创建代理类UserServiceImpl userService=(UserServiceImpl) proxy.getProxy(UserServiceImpl.class);userService.add();}

http://www.ppmy.cn/news/1047857.html

相关文章

5.1 webrtc线程模型

那从今天开始呢?我们来了解一下y8 tc线程相关的内容,那在开始之前呢?我们先来看一下,我们本章都要讲解哪些知识? 那第一个呢?是线程的基础知识,这块内容呢?主要是为大家做一下回顾&a…

chatGPT-对话爱因斯坦

引言 阿尔伯特爱因斯坦( 1879年 3 月 14 日 – 1955 年 4 月 18 日)是一位出生于德国的理论物理学家,被广泛认为成为有史以来最伟大、最有影响力的科学家之一。他以发展相对论而闻名,他还对量子力学做出了重要贡献,因…

UE4/5数字人MetaHuman的控制绑定资产使用

目录 开始操作 找到控制绑定资产 放入控制绑定资产 ​编辑 生成动画资产 开始操作 首先我们创建一个关卡序列: 打开后将我们的数字人放进去【右键,第一个添加进去】: 我们会自动进入动画模式,没有的话,就自己…

Mac上传项目源代码到GitHub的修改更新

Mac上传项目源代码到GitHub的修改更新 最近在学习把代码上传到github,不得不说,真的还挺方便 这是一个关于怎样更新项目代码的教程。 首先,在本地终端命令行打开至项目文件下第一步:查看当前的git仓库状态,可以使用git…

Mac OS 中JDK 环境(jdk 1.8.0_831)安装配置、环境变量配置及卸载操作

前言: 摊牌了,本来就有点喜新厌旧的我,特意把系统和开发环境都拉到比较高,想试验一下兼容性和某些新特性,探索了一下新大陆,也见识了各种光怪陆离的妖魔鬼怪。 因为要着手云平台项目的重构改版和新系统的架…

openstack搭建

1 设置root密码:sudo passwd root 2 网络配置:虚拟机安装是选择nat映射,系统安装成功后直接配置vmnet8的地址段即可(操作系统正常安装即可,虚拟机内存大于4G即可); 3 安装ssh 在命令行输入 “su…

语法篇--XML数据传输格式

一、XML概述 1.1简介 XML,全称为Extensible Markup Language,即可扩展标记语言,是一种用于存储和传输数据的文本格式。它是由W3C(万维网联盟)推荐的标准,广泛应用于各种系统中,如Web服务、数据…

03.有监督算法——决策树

1.决策树算法 决策树算法可以做分类,也可以做回归 决策树的训练与测试: 训练阶段:从给定的训练集构造出一棵树(从根节点开始选择特征,如何进行特征切分) 测试阶段:根据构造出来的树模型从上…