动态代理看这个就一目了然

动态代理的总结

1.动态代理分类

我们设计一个应用的场景:

以前的导演剧组找演员的时候,直接到家里找这个演员谈价格就可以让他演戏,但是随着时代的发展,出现了经济公司,签约演员。 现在让演员演出就要直接找经济公司,不能找演员。

1.1基于接口的动态代理

// 创建一个演员的角色
public class Actor implements IActor {
?
    /**
     * 基本表演
     * @param money
     */
    @Override
    public void basicAct(Float money){
        System.out.println("拿到钱,开始基本的表演:"+money);
    }
?
    /**
     * 危险的表演
     * @param money
     */
    @Override
    public void dangerAct(Float money){
        System.out.println("拿到钱,开始危险的表演:"+money);
    }
}
?
?
?
// 模拟经济公司的标准
public interface IActor {
    /**
     * 基本表演
     * @param money
     */
    public void basicAct(Float money);

    /**
     * 危险的表演
     * @param money
     */
    public void dangerAct(Float money);
}
?

然后我们模拟一个剧组,通过经济公司来找演员,但是经济公司也有自己的标准,就是参数money

public class Client {
?
    public static void main(String[] args) {
        //早期:直接去家里找
        Actor actor = new Actor();
?
        //通过经纪公司来找演员
?
        IActor proxyActor = (IActor)Proxy.newProxyInstance(actor.getClass().getClassLoader(), actor.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * 此处提供增强的代码
                     * 执行被代理对象的任何方法,都会经过该方法。
                     * @param proxy     代理对象的引用
                     * @param method    当前执行的方法
                     * @param args      当前方法所需的参数
                     * @return          和被代理对象的方法具有相同的返回值
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object rtValue = null;
                        //1.取出当前方法的参数
                        Float money= (Float) args[0];
                        //2.判断方法是什么
                        if("basicAct".equals(method.getName())){
                            //基本演出:抽取20% 要求一天5000块以上才接
                            if(money > 5000f){
                                rtValue = method.invoke(actor,money*0.8f);
                            }
                        }
                        if("dangerAct".equals(method.getName())){
                            //高危演出:抽取10% 要求一天20000块以上才接
                            if(money > 20000f){
                                rtValue = method.invoke(actor,money*0.9f);
                            }
                        }
                        return rtValue;
                    }
                });
?
?
        proxyActor.basicAct(10000f);
        proxyActor.dangerAct(50000f);
    }
}
?

运行结果:

拿到钱,开始基本的表演:8000.0拿到钱,开始危险的表演:45000.0

总结:

 动态代理基于接口         *  作用:不修改源码的基础上,对已有方法增强         *  特点:字节码是随用随创建,随用随加载。         *  基于接口的动态代理:         *  提供者:JDK官方         *  要求:被代理对象最少实现一个接口。         *  涉及的类:Proxy         *  涉及的方法:newProxyInstance         *  方法的参数:         *      ClassLoader:类加载器。负责加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。         *      Class[]:字节码数组。代理对象具有的方法。和被代理对象实现相同的接口。         *               如果被代理对象本身是一个接口的话,直接把被代理对象存入字节码数组中。         *               xxx.getClass().getInterfaces() || new Class[]{xxx}         *               固定写法。         *      InvocationHandler:如何代理的接口。谁用谁写。用于增强方法的。需要我们自己提供一个该接口的实现类。         *                         通常情况下可以写成匿名内部类。         *                         策略模式:         *                              数据已经有了         *                              目的明确。         *                              达成目标的过程即是策略。

1.2基于子类的动态代理

public class Actor {
?
     /**
     * 基本表演
     * @param money
     */
?
    public void basicAct(Float money){
        System.out.println("拿到钱,开始基本的表演cglib:"+money);
    }
?
     /**
     * 危险的表演
     */

?
    public void dangerAct(Float money){
        System.out.println("拿到钱,开始危险的表演cglib:"+money);
    }
}
?
?
?
?
public class Client {
?
    public static void main(String[] args) {
        // 早期:直接去家里找
        // Actor actor = new Actor();
        // 通过经纪公司来找演员
/**
         * 动态代理
         *  作用:不修改源码的基础上,对已有方法增强
         *  特点:字节码是随用随创建,随用随加载。
         *  基于子类的动态代理:
         *  提供者:第三方cglib库
         *  要求:被代理对象不能是最终类。不能被final修饰
         *  涉及的类:Enhancer
         *  涉及的方法:create
         *  方法的参数:
         *      Class:字节码。被代理对象的字节码。固定写法。
?
         *      Callback:如何代理的接口。谁用谁写。用于增强方法的。需要我们自己提供一个该接口的实现类。
         *                         通常情况下可以写成匿名内部类。
         *                         我们需要使用它的子接口:MethodInterceptor
         *                         策略模式:
         *                              数据已经有了
         *                              目的明确。
         *                              达成目标的过程即是策略。
         *
         */
        Actor cglibActor = (Actor) Enhancer.create(actor.getClass(), new MethodInterceptor() {

             /**
             * 此处提供增强的代码
             * 执行被代理对象的任何方法,都会经过该方法。
             * @param proxy         代理对象的引用
             * @param method        当前执行的方法
             * @param args          当前方法所需的参数
             * @param methodProxy   当前方法的代理对象
             * @return              和被代理对象的方法具有相同的返回值
             * @throws Throwable
             */
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object rtValue = null;
                // 1.取出当前方法的参数
                Float money= (Float) args[0];
                // 2.判断方法是什么
                if("basicAct".equals(method.getName())){
                    // 基本演出:抽取20% 要求一天5000块以上才接
                    if(money > 5000f){
                        rtValue = method.invoke(actor,money*0.75f);
                    }
                }
                if("dangerAct".equals(method.getName())){
                    // 高危演出:抽取10% 要求一天20000块以上才接
                    if(money > 20000f){
                        rtValue = method.invoke(actor,money*0.85f);
                    }
                }
                return rtValue;
            }
        });
        cglibActor.basicAct(10000f);
        cglibActor.dangerAct(50000f);
    }
}

原文地址:https://www.cnblogs.com/mudi/p/9844536.html

时间: 2024-10-15 04:37:40

动态代理看这个就一目了然的相关文章

你真的完全了解Java动态代理吗?看这篇就够了

之前讲了<零基础带你看Spring源码--IOC控制反转>,本来打算下一篇讲讲Srping的AOP的,但是其中会涉及到Java的动态代理,所以先单独一篇来了解下Java的动态代理到底是什么,Java是怎么实现它的. 动态代理看起来好像是个什么高大上的名词,但其实并没有那么复杂,直接从字面就很容易理解.动态地代理,可以猜测一下它的含义,在运行时动态地对某些东西代理,代理它做了其他事情.先不去搞清楚这个动态代理真正的含义,我们来举个生动的例子来理解下它到底做了什么. 一个例子 一个程序员Devel

关于java的一个典型的动态代理

今天看书的一个过程中,看到一个动态代理看下代码 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxy { public static void testDynamicProxy(){ Calculator calculator = new CalculatorImpl(); LogH

Java代理/静态代理/动态代理/代理模式

代理模式:即Proxy Pattern,常用的设计模式之一.代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问. 代理概念 :为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类处理.以及委托类执行完请求后的后续处理. 下面以明星为例模拟需求说明静态代理和动态代理. 一.首先看静态代理 看下图:歌迷希望明星许巍唱歌(许巍即是目标对象),但不可能直接找

Apache commons Proxy简介和动态代理、动态拦截器实现

Apache Commons Proxy 是Apache 的一个之项目,封装了 Java 对象代理的一些常用方法.又叫做 动态代理. 动态代理的作用非常大,在很多底层框架中都会用得到,比如struts,Spring等都用到了动态代理,它的原理很简单,就是将你要使用的类,重新生成一个子类或本类,这样框架就可以利用这个新生成的类做一些事情,比如在该类的方法前后加一些代码. 设想一下,不用修改任何已经编写好的代码,只要使用动态代理就可以灵活的加入一些东西,将来要是不喜欢了,不用也不会影响原来的代码.

小白也能看懂的插件化DroidPlugin原理(一)-- 动态代理

前言:插件化在Android开发中的优点不言而喻,也有很多文章介绍插件化的优势,所以在此不再赘述.前一阵子在项目中用到 DroidPlugin 插件框架 ,近期准备投入生产环境时出现了一些小问题,所以决心花些时间研究了一下 DroidPlugin 插件框架的原理,以便再出现问题时也能从容应对.打开源码后发现尽是大把大把的 hook.binder.classloader 等等,很难摸清头绪,幸运的是,有很多热心的大神已经对 DroidPlugin 的原理进行了透彻的剖析,文末会有本人对参考文章的致

[jvm解析系列][十四]动态代理和装饰模式,带你看源码深入理解装饰模式和动态代理的区别。

不知道大家知不知道设计模式中有一种叫做装饰,举一个简单的例子. 一天一个年轻领导小王讲话:咳咳,我们一定要xxx抓紧xxxx学习xxx的精神!好,今天的会议结束! 然后有一个老领导李同志接过来说:那个我在补充两点,个别同志xxx,一定要注意xxx.好散会. 然后另一天小王同志又在讲话:xxx两手都要抓,xxxx一定要注意. 这个时候老周同志出来了:嗯,小王讲的很好,我还有几点要补充xxxx. 那么很明显,小王同志的讲话方法不是很让人满意,那么老李领导或者老周领导可以接过来继续装修一下.其实这就是

[动态代理三部曲:中] - 从动态代理,看Class文件结构定义

前言 这篇内容是上一篇[动态代理三部曲:上] - 动态代理是如何"坑掉了"我4500块钱的补充,进一步分析篇.建议二者结合食用,醇香绵软,入口即化. 好了,不扯淡了,开始... 正文 2.Class 文件的格式 这里为啥是2开头呢?因为上篇文章是1 这部分内容不知道各位小伙伴是怎么感觉的.最开始学习的时候,我是一头雾水,不知道如何下手.当一步步结合反射.JVM内存模型,类加载机制后.再回过头来就会发现一起豁然开朗. 此篇内容的开始,让我们根据我们demo中所用的类:RentHouseP

什么静态/动态代理,内容详解,只要看就会懂

静态代理:自己创建代理类生成源代码再对其编译.在程序运行前代理类的.class文件就已经存在了. 动态代理: 自动:可以根据我们的真实对象接口,自动生成一个增强型代码,而不要手动创建代理类写增强逻辑 运行时:可以在代码运行时,生成这个代理类,而不需要事先把这个类写好 废话少说,直接上代码 代码设计原则: 静态代理实现: 一.创建接口 1 public interface IGamePlayer { 2 3 //登录 4 public void login(String username ,Str

JDK动态代理实现原理

之前虽然会用JDK的动态代理,但是有些问题却一直没有搞明白.比如说:InvocationHandler的invoke方法是由谁来调用的,代理对象是怎么生成的.直到看了他的文章才彻底明白,附网址:http://rejoy.iteye.com/blog/1627405 Java代码   package dynamic.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import j