一篇文章带你搞定什么是动态代理

编程入门 行业动态 更新时间:2024-10-09 05:18:17

一篇文章<a href=https://www.elefans.com/category/jswz/34/1769690.html style=带你搞定什么是动态代理"/>

一篇文章带你搞定什么是动态代理

文章目录

    • 一、动态代理的特点
    • 二、基于接口的动态代理
    • 三、基于子类的动态代理

一、动态代理的特点

字节码随用随创建,随用随加载。
它与静态代理的区别也在于此,因为静态代理是字节码一上来就创建好,并完成加载
装饰者模式就是静态代理的一种体现。
(1) 基于接口的动态代理:
提供者: JDK 官方的 Proxy 类。
要求:被代理类最少实现一个接口。

(2)基于子类的动态代理
提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar
要求:被代理类不能用 final 修饰的类(最终类)。

二、基于接口的动态代理

案例:在很久以前,演员和剧组都是直接见面联系的。没有中间人环节。而随着时间的推移,产生了一个新兴职业:经纪人(中间人),这个时候剧组再想找演员就需要通过经纪人来找了。下面我们就用代码演示出来。

创建代理对象:使用Proxy类中的newProxyInstance方法
创建代理对象的要求:被代理类最少实现一个接口,如果没有则不能使用

newProxyInstance方法的参数:* ClassLoader 类加载器:它是用于加载代理对象字节码的,和被代理对象使用相同的类加载器,固定写法。* Class[] 字节码数组:它是用于让代理对象和被代理对象有相同方法,固定写法。* InvocationHandler:用于提供增强的代码* 它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。* 此接口的实现类都是谁用谁写。

(1)演员类

/*** 一个演员* 实现了接口,就表示具有接口中的方法实现。即:符合经纪公司的要求*/
public class Actor implements IActor {@Overridepublic void basicAct(float money) {System.out.println("拿到钱,开始基本的表演:" + money);}@Overridepublic void dangerAct(float money) {System.out.println("拿到钱,开始危险的表演:" + money);}
}

(2)经纪公司接口

/*** 一个经纪公司的要求:*      能做基本的表演和危险的表演*/
public interface IActor {/*** 基本演出* @param money*/public void basicAct(float money);/*** 危险演出* @param money*/public void dangerAct(float money);
}

(3)模拟消费者

public class Client {public static void main(String[] args) {//一个剧组直接找演员final Actor actor = new Actor();//创建代理对象的要求:被代理类最少实现一个接口,如果没有则不能使用IActor proxyActor = (IActor) Proxy.newProxyInstance(actor.getClass().getClassLoader(),actor.getClass().getInterfaces(),new InvocationHandler() {/*** 执行被代理对象的任何方法,都会经过该方法。* 此方法有拦截的功能。** 参数:* proxy:代理对象的引用。不一定每次都用得到* method:当前执行的方法对象* args:执行方法所需的参数* 返回值:* 当前执行方法的返回值*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String name = method.getName();Float money = (Float) args[0];Object rtValue = null;if ("dangerAct".equals(name)) {//危险演出,没有5000不演if (money > 5000) {//剧组扣除一半,演员到手一半,这里实际对方法进行了增强rtValue = method.invoke(actor, money / 2);}}return rtValue;}});//1.没有经纪公司,直接找演员actor.dangerAct(5000f);//2.通过经纪公司联系演员proxyActor.dangerAct(50000f);}
}

三、基于子类的动态代理

涉及的类:Enhancer
提供者:第三方cglib库<!--实现基于子类的动态代理的cglib库--><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.1_3</version>
</dependency>
如何创建代理对象:* 使用Enhancer类中的create方法* 创建代理对象的要求:被代理类不能是最终类* create方法的参数:* Class:字节码,它是用于指定被代理对象的字节码。* Callback:用于提供增强的代码,它是让我们写如何代理。* 我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。* 此接口的实现类都是谁用谁写。* 我们一般写的都是该接口的子接口实现类:MethodInterceptor

(1)Actor类不需要接口

/*** 一个演员:此处未实现任何接口*/
public class Actor {public void basicAct(float money) {System.out.println("拿到钱,开始基本的表演: " + money);}public void dangerAct(float money) {System.out.println("拿到钱,开始危险的表演: " + money);}
}

(2)

public class Client {public static void main(String[] args) {final Actor actor = new Actor();/*** 基于子类的动态代理* 要求:被代理对象不能是最终类* 用到的类:Enhancer* 用到的方法:create(Class, Callback)* 方法的参数:* Class:被代理对象的字节码* Callback:如何代理* @param args*/Actor cglibActor = (Actor) Enhancer.create(actor.getClass(),new MethodInterceptor() {/*** 执行被代理对象的任何方法,都会经过该方法。在此方法内部就可以对被代理对象的任何方法进行增强。* 参数:* 前三个和基于接口的动态代理是一样的。* MethodProxy:当前执行方法的代理对象。* 返回值:当前执行方法的返回值*/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {String name = method.getName();Float money = (Float) objects[0];Object rtValue = null;if("dangerAct".equals(name)){//危险演出if(money > 5000){rtValue = method.invoke(actor, money/2);}}return rtValue;}});cglibActor.dangerAct(100000);}
}

更多推荐

一篇文章带你搞定什么是动态代理

本文发布于:2024-02-07 02:26:40,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1752179.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:带你   一篇文章   动态

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!