学习Java——代理
创始人
2025-05-31 06:37:25
0

目录

静态代理

动态代理

动态代理的几种实现方式

Java实现动态代理的大致步骤

Java 实现动态代理主要涉及哪几个类 

动态代理实现 

jdk动态代理

cglib动态代理

AOP

每日寄语


静态代理

所谓静态代理,就是代理类是由程序员自己编写的,在编译期就确定好了的。来看下下面的例子:

public interface HelloSerivice {public void say();
}public class HelloSeriviceImpl implements HelloSerivice{@Overridepublic void say() {System.out.println("hello world");}
}

上面的代码比较简单,定义了一个接口和其实现类。这就是代理模式中的目标对象和目标对象的接口。接下来定义代理对象。

public class HelloSeriviceProxy implements HelloSerivice{private HelloSerivice target;public HelloSeriviceProxy(HelloSerivice target) {this.target = target;}@Overridepublic void say() {System.out.println("记录日志");target.say();System.out.println("清理数据");}
}

上面就是一个代理类,他也实现了目标对象的接口,并且扩展了say方法。下面是一个测试类:

public class Main {@Testpublic void testProxy(){//目标对象HelloSerivice target = new HelloSeriviceImpl();//代理对象HelloSeriviceProxy proxy = new HelloSeriviceProxy(target);proxy.say();}
}

这就是一个简单的静态的代理模式的实现。代理模式中的所有角色(代理对象、目标对象、目标对象的接口)等都是在编译期就确定好的。

 静态代理的用途

1.控制真实对象的访问权限:通过代理对象控制真实对象的使用权限。

2.避免创建大对象:通过使用一个代理小对象来代表一个真实的大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。

3.增强真实对象的功能:这个比较简单,通过代理可以在调用真实对象的方法的前后增加额外功能。

动态代理

        前面介绍了静态代理,虽然静态代理模式很好用,但是静态代理还是存在一些局限性的,比如使用静态代理模式需要程序员手写很多代码,这个过程是比较浪费时间和精力的。一旦需要代理的类中方法比较多,或者需要同时代理多个对象的时候,这无疑会增加很大的复杂度。

有没有一种方法,可以不需要程序员自己手写代理类呢。这就是动态代理啦。

动态代理中的代理类并不要求在编译期就确定,而是可以在运行期动态生成,从而实现对目标对象的代理功能。

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

动态代理的几种实现方式

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

1、JDK动态代理:java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。

2、Cglib动态代理:Cglib (Code Generation Library )是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。

关于这两种动态代理的写法本文就不深入展开了,读者感兴趣的话,后面我再写文章单独介绍。本文主要来简单说一下这两种动态代理的区别和用途。

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

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

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

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

Cglib与动态代理最大的区别就是:

使用动态代理的对象必须实现一个或多个接口

使用cglib代理的对象则无需实现接口,达到代理类无侵入。

Java实现动态代理的大致步骤

1、定义一个委托类和公共接口。

2、自己定义一个类(调用处理器类,即实现 InvocationHandler 接口),这个类的目的是指定运行时将生成的代理类需要完成的具体任务(包括Preprocess和Postprocess),即代理类调用任何方法都会经过这个调用处理器类(在本文最后一节对此进行解释)。

3、生成代理对象(当然也会生成代理类),需要为他指定(1)委托对象(2)实现的一系列接口(3)调用处理器类的实例。因此可以看出一个代理对象对应一个委托对象,对应一个调用处理器实例。

Java 实现动态代理主要涉及哪几个类 

        java.lang.reflect.Proxy: 这是生成代理类的主类,通过 Proxy 类生成的代理类都继承了 Proxy 类,即 DynamicProxyClass extends Proxy。

        java.lang.reflect.InvocationHandler: 这里称他为"调用处理器",他是一个接口,我们动态生成的代理类需要完成的具体内容需要自己定义一个类,而这个类必须实现 InvocationHandler 接口。

动态代理实现 

使用动态代理实现功能:不改变Test类的情况下,在方法target 之前打印一句话,之后打印一句话。

public class UserServiceImpl implements UserService {@Overridepublic void add() {// TODO Auto-generated method stubSystem.out.println("--------------------add----------------------");}
}

jdk动态代理

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 {PerformanceMonior.begin(target.getClass().getName()+"."+method.getName());//System.out.println("-----------------begin "+method.getName()+"-----------------");Object result = method.invoke(target, args);//System.out.println("-----------------end "+method.getName()+"-----------------");PerformanceMonior.end();return result;}public Object getProxy(){return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);}}public static void main(String[] args) {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();  }  //实现MethodInterceptor接口方法  public Object intercept(Object obj, Method method, Object[] args,  MethodProxy proxy) throws Throwable {  System.out.println("前置代理");  //通过代理类调用父类中的方法  Object result = proxy.invokeSuper(obj, args);  System.out.println("后置代理");  return result;  }  
}  public class DoCGLib {  public static void main(String[] args) {  CglibProxy proxy = new CglibProxy();  //通过生成子类的方式创建代理类  UserServiceImpl proxyImp = (UserServiceImpl)proxy.getProxy(UserServiceImpl.class);  proxyImp.add();  }  
}

AOP

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

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

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

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


关于代理,之前我也总结过相关博客,链接放在下面,有兴趣的可以学习参考:

java——代理_别活在过去i的博客-CSDN博客

cglib动态代理_别活在过去i的博客-CSDN博客

了解一下Spring AOP_别活在过去i的博客-CSDN博客


每日寄语

        人这一辈子千万不要马虎做两件事:一是找对事业,二是找对爱人,因为太阳升起时要投身事业,太阳落下时要与爱人相拥,我们终其一生都在寻找两样东西,一是价值感二是归属感。价值感来源于肯定,归属感来源于被爱。人要有日出时的自豪感也要享受日落时的相拥——葛优

相关内容

热门资讯

Redis 内存管理(淘汰策略... 目录Redis 内存管理(淘汰策略/删除策略)一、淘汰算法1、LRU算法...
用问答的方式学习Require 我需要在vue3中引入require,该怎么导入? 在 Vue 3 中...
关于会计职业生涯规划书模板 会... 篇一:会计职业生涯规划模板  今天站在哪里并不重要,最重要的是你下一步迈向哪里。职业生涯规划对于每个...
护理职业生涯规划书模板 护理职... 篇一:护士的职业生涯规划书范文  时间: (****年-****年,**岁至**岁)  美好愿望:工...
工商管理专业职业生涯规划书 工...  工商管理专业职业生涯规划书(一)  一、自我分析  我是一个真诚的人。为什么我会把真诚写在第一位?...
大学生职业生涯规划书精选 计算... 【1】大学生职业生涯规划书范文  第一章:总论(引言)实现梦想的第一步就是要有梦想。没有梦想对于每个...
药学专业职业生涯规划书 大专药...  药学专业职业生涯规划书(一)  岁月流光,转瞬即逝,我将迈入大一的生活中去。迈入新的一年里,应该有...
【TypeScript 入门】... 前两个章节都是介绍 TypeScript 中最基础的语法和特性的,这一章,我们讲 TypeScrip...
语义分割网络论文集锦 年份会议/期刊标题内容架构图2015CVPRFully Convolutional Networks...
数学系职业生涯规划书 数学类职...   数学系职业生涯规划书(一)  数学是解决问题的语言,是所有科学和技术的核心。接受数学教育的优点是...
国贸系职业生涯规划书 国贸专业...   国贸系职业生涯规划书(一)  一、前言:职业规划意义  每一个人都拥有自己的梦想,然而并非每一个...
哲学系职业生涯规划书范文 分析...  哲学系职业生涯规划书(一)  一、前言  未来,掌握在自己手中。踏着时光车轮,我已走到23岁的年轮...
法学系职业生涯规划书 法学职业...   法学系职业生涯规划书(一)  一、前言  从我们走入大学校门到现在已经快要一年了,现在我们的大一...
物流管理专业职业生涯规划书 物... 第一部分 物流管理师职业前景分析  我国物流产业兴起于上世纪 90年代,起步虽晚,但发展势头强劲,到...
小波包分解提取 %% wavelet packet coefficients. 求取小波包分解的各个节点的小波包系数...
算法小抄9-快慢指针 在上一节我们已经讲过了怎么使用快慢指针去寻找链表的中点,这一节我们继续学习快慢指针的进阶用法,快慢指...
机械学院职业生涯规划书 机械工...  机械学院职业规划书(一)  第一章 认识自我  尼采曾说:“聪明的人只要能认识自己,便什么都不会失...
化学系职业规划书范文 化学系大...   化学系职业规划书(一)  一。 前言  社会的发展日异月新,社会的竞争越来越大,大学生越来越多,...
土木工程学院职业生涯规划书 土...   土木工程学院职业生涯规划书(一)  一、前言  莎士比亚曾说过:“人生就是一部作品。谁有生活理想...
利用python写一个gui小... 文章目录前言制作设计自己想要的ui举个例子后记 前言 在上文中我们配置好了GUI编译环境࿰...