动态代理就先说代理模式,然后是动态代理
代理模式中,会有代理对象,和被代理对象(目标业务对象)。代理对象会拦截对目标业务对象的访问。类似于现实中的老师和经纪人。
/** 老师的接口*/public interface drawer {public void sing(double money);public void draw(double money);public void sleep();}
/** 一个具体的老师:徐老师*/public class Xulaoshi implements drawer {@Overridepublic void sing(double money) {System.out.println("徐老师教了一首歌!");System.out.println("徐老师赚了" + money + "RMB");}@Overridepublic void draw(double money) {System.out.println("徐老师教了一节画画!");System.out.println("徐老师赚了" + money + "RMB");}@Overridepublic void sleep() {System.out.println("徐老师太累了。。。休息一会儿");}}/** 代理类A,代理徐老师*/public class A implements drawer {// 持有真实业务对象private drawer s;// 接收真实业务对象public A(drawer s) {this.s = s;}@Overridepublic void sing(double money) {// 做一个拦截if (money < 100000) {System.out.println("钱太少,不去");return;}System.out.println("A抽取" + money * 0.6 + "提成");s.sing(money * 0.4);}@Overridepublic void draw(double money) {// 做一个拦截if (money < 500000) {System.out.println("钱太少,加钱!");return;}System.out.println("A抽取" + money * 0.6 + "提成");s.draw(money * 0.4);}@Overridepublic void sleep() {System.out.println("帮忙定个酒店。。。");s.sleep();}}
/** 演示:代理模式* 代理:代理对象主要用来拦截目标业务对象(被代理对象)的访问。* A:代理对象要持有真实业务对象。(通过构造函数接收业务对象,并用成员变量记录)* B:代理对象要和真实业务对象,具备相同的行为方法(实现相同接口)* C:代理对象拦截对真实对象的访问,可以修改访问的参数、返回值,甚至拦截访问* 代理模式与装饰模式区别* A:代理模式侧重与拦截,装饰模式侧重与加强* B:Java中自带的代理中,只能对接口进行代理。装饰只需要与被装饰类有共同父类。*/public class ProxyDemo01 {public static void main(String[] args) {// 创建被代理对象Xulaoshi Xulaoshi = new Xulaoshi();// 创建代理对象A a= new A(Xulaoshi);// 访问方法a.sing(500);System.out.println("----------");a.draw(1000000);System.out.println("----------");a.sleep();}}
/** 演示:动态代理* 动态代理:在程序运行过程中产生的一个代理对象* 在程序运行的过程中,动态在内存中生成一个类,代理需要被代理的目标对象,并且生成这个代理类的对象。* Java如何凭空生成一个代理类,并且代理徐老师的呢?我们要查看一个API:* static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)* ClassLoader loader :类加载器,一般用被代理对象的类加载器* Class[] interfaces : 被代理对象的接口的Class对象数组,Class<?>[] getInterfaces() * InvocationHandler h : 调用处理器*/public class ProxyDemo02 {public static void main(String[] args) {// 创建被代理对象final Xulaoshi Xulaoshi = new Xulaoshi();// 先准备动态代理的三大参数// 被代理类的类加载器ClassLoader loader =Xulaoshi .getClass().getClassLoader();// 被代理对象的接口的Class对象数组Class<?>[] interfaces =Xulaoshi .getClass().getInterfaces();//Xulaoshi .getClass().getInterfaces();{drawer.class}// 调用处理器InvocationHandler h = new InvocationHandler(){// 当我们调用代理对象的功能时,代理对象,其实都来调用了处理器中的invoke功能// 因此,我们需要在invoke中写拦截的逻辑!public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// Object proxy : 是代理对象本身// Method method :当前正在被调用的真实方法的对象// Object[] args : 当前正在被调用的真实方法的真实参数String name = method.getName();// 判断方法的名称,做出不同的拦截逻辑if( "sing".equals(name) || "draw".equals(name)){double money = (double) args[0];double min = "sing".equals(name) ? 100000 : 500000;if (money < min) {System.out.println("钱太少,不去");return null;}System.out.println("A抽取" + money * 0.6 + "提成");return method.invoke(Xulaoshi, money * 0.4);}return method.invoke(Xulaoshi, args);}};// static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)drawer p = (drawer) Proxy.newProxyInstance(loader, interfaces, h);p.sing(100);p.draw(1000000);p.sleep();}}
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦