精华内容
下载资源
问答
  • JAVA动态代理代码示例

    千次阅读 2019-04-11 13:49:28
    代理是一种软件设计模式,目的地希望能做到代码重用。代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法。这个就好比 商户---->明星经纪人(代理)---->明星这种模式。我们可以不通过...

    概念理解

    代理是一种软件设计模式,目的地希望能做到代码重用。代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法。这个就好比 商户---->明星经纪人(代理)---->明星这种模式。我们可以不通过直接与明星对话的情况下,而通过明星经纪人(代理)与其产生间接对话,JAVA中的代理分为两种。

    静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

    动态代理类:在程序运行时,运用反射机制动态创建而成。

    实现方式

    动态代理的实现方式有两种第一种JDK自带的,缺点代理委托类必须是实现接口方法,具有致命的局限性,而第二种CgLib则屏蔽了这个局限性,可以代理任意委托类的方法,但是Cglib代理实现,借助了ASM字节码生成框架编写继承我们委托类的代理类字节码,所以如果委托类被修饰为 final,那CGLIB 代理不了。

    实体类:student对象

    /**
     * @author shengtao
     * @Description:
     * @date 2019/04/11 9:56
     */
    public class Student {
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        private String name;
    
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) throws IOException{
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
    }

    JDK代理类示例:

    接口类:IStudentService

    /**
     * @author shengtao
     * @Description:
     * @date 2019/04/11 12:36
     */
    public interface IStudentService {
    
        Student createStudent(String name ,int age);
    
    }
    

    IStudentService接口的实现类:StudentServiceImpl

    
    public class StudentServiceImpl implements IStudentService {
    
        @Override
        public Student createStudent(String name ,int age) {
            Student student = new Student("lishengtao",32);
            return student;
        }
    }

    实现了InvokationHandler的代理对象:DynamicProxy

    /**
     * @author shengtao
     * @Description:
     * @date 2019/04/11 12:40
     */
    public class DynamicProxy implements InvocationHandler {
    
        private Object target;
    
        public DynamicProxy(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("执行开始");
            Object obj = method.invoke(target,args);
            System.out.println("执行结束");
            return obj;
        }
    }
    

    JDK动态代理测试类:DynamicTest

    /**
     * @author shengtao
     * @Description:
     * @date 2019/04/11 12:42
     */
    public class DynamicTest {
    
        public static void main(String[] args){
            IStudentService studentService = new StudentServiceImpl();
    
            InvocationHandler invocationHandler = new DynamicProxy(studentService);
    
            IStudentService proxy = (IStudentService) Proxy.newProxyInstance(studentService.getClass().getClassLoader(),studentService.getClass().getInterfaces(),invocationHandler);
    
            Student student = proxy.createStudent("李胜涛",22);
    
            System.out.println(ToStringBuilder.reflectionToString(student));
        }
    
    
    }
    
    
    运行结果:
    
    执行开始
    执行结束
    com.lesent.model.reflection.Student@77cd7a0[name=lishengtao,age=32]

    CgLib实现动态代理示例

    编写代码前引入Cglib的依赖:pom.xml添加

    <!-- https://mvnrepository.com/artifact/cglib/cglib -->
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.2.10</version>
    </dependency>
    

    被代理对象及方法实现:StudentServiceImpl2

    public class StudentServiceImpl2 {
    
        public Student createStudent(String name ,int age) {
            Student student = new Student("lishengtao",32);
            return student;
        }
    }

    代理方法接口实现:InterCeptorHandler 

    class InterCeptorHandler implements MethodInterceptor{
    
        public Object getProxy(Class<?> clazz){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
            //设置回调方法
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            //切记不要使用 method.invoke(o,objects) 和 methodProxy.invoke(o, args); 否则会死循环
            System.out.println("执行开始");
            Object o1 = methodProxy.invokeSuper(o,objects);
            System.out.println("执行结束");
    
            return o1;
        }
    }

    代理测试类:DynamicProxy

    /**
     * @author shengtao
     * @Description:
     * @date 2019/04/11 13:19
     */
    public class DynamicProxy {
    
        public static void main(String[] args){
            InterCeptorHandler interCeptorHandler = new InterCeptorHandler();
            StudentServiceImpl2 studentServiceImpl2 = (StudentServiceImpl2) interCeptorHandler.getProxy(StudentServiceImpl2.class);
            Student student = studentServiceImpl2.createStudent("李胜涛",22);
            System.out.println(ToStringBuilder.reflectionToString(student));
        }
    
    }
    

     

    展开全文
  • 代理模式代码

    2017-09-20 00:04:40
    为其他对象提供一种代理以控制对这个对象的访问。这里的代码示例使保护代理代码,再其中使用的Java的动态代理
  • 最易懂的设计模式解析在目标对象较多的情况下,若采用静态代理,则会出现静态代理对象量多、代码量大,从而导致代码复杂的问题采用动态代理模式。设计动态代理类(DynamicProxy)时,不需要显式实现与目标对象类...
  • 秒懂Java代理与动态代理模式

    万次阅读 多人点赞 2018-06-30 17:08:23
    什么是动态代理模式?二者什么关系?具体如何实现?什么原理?如何改进?这即为我们学习一项新知识的正确打开方式,我们接下来会以此展开,让你秒懂。 概念 什么是代理模式 定义:为其他对象提供一种代理以控制...

    版权申明】非商业目的可自由转载
    博文地址:https://blog.csdn.net/shusheng0007/article/details/80864854
    出自:shusheng007

    设计模式汇总篇,一定要收藏:

    永不磨灭的设计模式(有这一篇真够了,拒绝标题党)

    概述

    什么是代理模式?解决什么问题(即为什么需要)?什么是静态代理?什么是动态代理模式?二者什么关系?具体如何实现?什么原理?如何改进?这即为我们学习一项新知识的正确打开方式,我们接下来会以此展开,让你秒懂。

    类型

    结构型(structural)

    难度

    3颗星

    概念

    什么是代理模式

    定义:为其他对象提供一种代理以控制对这个对象的访问

    定义总是抽象而晦涩难懂的,让我们回到生活中来吧。

    实例:王二狗公司(天津在线回声科技发展有限公司)老板突然在发工资的前一天带着小姨子跑路了,可怜二狗一身房贷,被迫提起劳动仲裁,劳动局就会为其指派一位代理律师全权负责二狗的仲裁事宜。那这里面就是使用了代理模式,因为在劳动仲裁这个活动中,代理律师会全权代理王二狗。

    解决什么问题

    下面是一些使用场景,不过太抽象,暂时可以不要在意,随着你的不断进步你终究会明白的。

    • 远程代理 :为位于两个不同地址空间对象的访问提供了一种实现机制,可以将一些消耗资源较多的对象和操作移至性能更好的计算机上,提高系统的整体运行效率。
    • 虚拟代理:通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销。
    • 缓冲代理:为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,优化系统性能,缩短执行时间。
    • 保护代理:可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限。
    • 智能引用:要为一个对象的访问(引用)提供一些额外的操作时可以使用

    什么是静态代理

    静态代理是指预先确定了代理与被代理者的关系,例如王二狗的代理律师方文镜是在开庭前就确定的了。那映射到编程领域的话,就是指代理类与被代理类的依赖关系在编译期间就确定了。下面就是王二狗劳动仲裁的代码实现:

    首先定义一个代表诉讼的接口

    public interface ILawSuit {
        void submit(String proof);//提起诉讼
        void defend();//法庭辩护
    }
    

    王二狗诉讼类型,实现ILawSuit接口

    public class SecondDogWang implements ILawSuit {
        @Override
        public void submit(String proof) {
            System.out.println(String.format("老板欠薪跑路,证据如下:%s",proof));
        }
    
        @Override
        public void defend() {
            System.out.println(String.format("铁证如山,%s还钱","马旭"));
        }
    }
    

    代理律师诉讼类,实现ILawSuit接口

    public class ProxyLawyer implements ILawSuit {
    
        ILawSuit plaintiff;//持有要代理的那个对象
        public ProxyLawyer(ILawSuit plaintiff) {
            this.plaintiff=plaintiff;
        }
    
        @Override
        public void submit(String proof) {
            plaintiff.submit(proof);
        }
    
        @Override
        public void defend() {
            plaintiff.defend();
        }
    }
    

    产生代理对象的静态代理工厂类

    public class ProxyFactory {
        public static ILawSuit getProxy(){
            return new ProxyLawyer(new SecondDogWang());
        }
    }
    

    这样就基本构建了静态代理关系了,然后在客户端就可以使用代理对象来进行操作了。

        public static void main(String[] args) {
            ProxyFactory.getProxy().submit("工资流水在此");
            ProxyFactory.getProxy().defend();
        }
    

    输出结果如下:

    老板欠薪跑路,证据如下:工资流水在此
    铁证如山,马旭还钱
    

    可以看到,代理律师全权代理了王二狗的本次诉讼活动。那使用这种代理模式有什么好处呢,我们为什么不直接让王二狗直接完成本次诉讼呢?现实中的情况比较复杂,但是我可以简单列出几条:这样代理律师就可以在提起诉讼等操作之前做一些校验工作,或者记录工作。例如二狗提供的资料,律师可以选择的移交给法庭而不是全部等等操作,就是说可以对代理的对做一些控制。例如二狗不能出席法庭,代理律师可以代为出席。。。

    什么是动态代理

    动态代理本质上仍然是代理,情况与上面介绍的完全一样,只是代理与被代理人的关系是动态确定的,例如王二狗的同事牛翠花开庭前没有确定她的代理律师,而是在开庭当天当庭选择了一个律师,映射到编程领域为这个关系是在运行时确定的。

    那既然动态代理没有为我们增强代理方面的任何功能,那我们为什么还要用动态代理呢,静态代理不是挺好的吗?凡是动态确定的东西大概都具有灵活性,强扩展的优势。上面的例子中如果牛翠花也使用静态代理的话,那么就需要再添加两个类。一个是牛翠花诉讼类,一个是牛翠花的代理律师类,还的在代理静态工厂中添加一个方法。而如果使用动态代理的话,就只需要生成一个诉讼类就可以了,全程只需要一个代理律师类,因为我们可以动态的将很多人的案子交给这个律师来处理。

    Jdk动态代理实现

    在java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口、另一个则是 Proxy类,这个类和接口是实现我们动态代理所必须用到的。

    InvocationHandler接口是给动态代理类实现的,负责处理被代理对象的操作的,而Proxy是用来创建动态代理类实例对象的,因为只有得到了这个对象我们才能调用那些需要代理的方法。

    接下来我们看下实例,牛翠花动态指定代理律师是如何实现的。
    1.构建一个牛翠花诉讼类

    public class CuiHuaNiu implements ILawSuit {
        @Override
        public void submit(String proof) {
            System.out.println(String.format("老板欠薪跑路,证据如下:%s",proof));
        }
        @Override
        public void defend() {
            System.out.println(String.format("铁证如山,%s还牛翠花血汗钱","马旭"));
        }
    }
    

    2.构建一个动态代理类

    public class DynProxyLawyer implements InvocationHandler {
        private Object target;//被代理的对象
        public DynProxyLawyer(Object obj){
            this.target=obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    	    System.out.println("案件进展:"+method.getName());
            Object result=method.invoke(target,args);
            return result;
        }
    }
    

    3.修改静态工厂方法

    public class ProxyFactory {
    	...
    
        public static Object getDynProxy(Object target) {
            InvocationHandler handler = new DynProxyLawyer(target);
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
        }
    }
    

    4.客户端使用

        public static void main(String[] args) {
            ILawSuit proxy= (ILawSuit) ProxyFactory.getDynProxy(new CuiHuaNiu());
            proxy.submit("工资流水在此");
            proxy.defend();
        }
    

    输出结果为:

    案件进展:submit
    老板欠薪跑路,证据如下:工资流水在此
    案件进展:defend
    铁证如山,马旭还牛翠花血汗钱
    

    JDK动态代理实现的原理

    首先Jdk的动态代理实现方法是依赖于接口的,首先使用接口来定义好操作的规范。然后通过Proxy类产生的代理对象调用被代理对象的操作,而这个操作又被分发给InvocationHandler接口的 invoke方法具体执行

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    

    此方法的参数含义如下
    proxy:代表动态代理对象
    method:代表正在执行的方法
    args:代表当前执行方法传入的实参
    返回值:表示当前执行方法的返回值

    例如上面牛翠花案例中,我们使用Proxy类的newProxyInstance()方法生成的代理对象proxy去调用了proxy.submit("工资流水在此");操作,那么系统就会将此方法分发给invoke().其中proxy对象的类是系统帮我们动态生产的,其实现了我们的业务接口ILawSuit

    cgLib的动态代理实现

    由于JDK只能针对实现了接口的类做动态代理,而不能对没有实现接口的类做动态代理,所以cgLib横空出世!CGLib(Code Generation Library)是一个强大、高性能的Code生成类库,它可以在程序运行期间动态扩展类或接口,它的底层是使用java字节码操作框架ASM实现。

    1 引入cgLib 库
    cglib-nodep-3.2.6.jar:使用nodep包不需要关联asm的jar包,jar包内部包含asm的类.

    2 定义业务类,被代理的类没有实现任何接口

    public class Frank {
       public void submit(String proof) {
           System.out.println(String.format("老板欠薪跑路,证据如下:%s",proof));
       }
       public void defend() {
           System.out.println(String.format("铁证如山,%s还Frank血汗钱","马旭"));
       }
    }
    

    3 定义拦截器,在调用目标方法时,CGLib会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。

    public class cgLibDynProxyLawyer implements MethodInterceptor {
        @Override
        public Object intercept(Object o, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
            if (method.getName().equals("submit"))
                System.out.println("案件提交成功,证据如下:"+ Arrays.asList(params));
            Object result = methodProxy.invokeSuper(o, params);
            return result;
        }
    }
    

    4定义动态代理工厂,生成动态代理

    public class ProxyFactory {
        public static Object getGcLibDynProxy(Object target){
            Enhancer enhancer=new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(new cgLibDynProxyLawyer());
            Object targetProxy= enhancer.create();
            return targetProxy;
        }
    }
    

    5客户端调用

      public static void main(String[] args) {
            Frank cProxy= (Frank) ProxyFactory.getGcLibDynProxy(new Frank());
            cProxy.submit("工资流水在此");
            cProxy.defend();
        }
    

    输出结果:

    案件提交成功,证据如下:[工资流水在此]
    老板欠薪跑路,证据如下:工资流水在此
    铁证如山,马旭还Frank血汗钱
    

    可见,通过cgLib对没有实现任何接口的类做了动态代理,达到了和前面一样的效果。这里只是简单的讲解了一些cgLib的使用方式,有兴趣的可以进一步了解其比较高级的功能,例如回调过滤器(CallbackFilter)等。

    cgLib的动态代理原理

    CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。

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

    CGLIB缺点:对于final方法,无法进行代理。

    动态代理在AOP中的应用

    什么是AOP? 维基百科上如是说:

    定义:In computing, aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns.
    AOP是一种编程范式,其目标是通过隔离切面耦合来增加程序的模块化。

    首先声明,AOP是OOP的补充,其地位及其重要性远不及OOP,总体来说OOP面向名词领域而AOP面向动词领域,例如对一个人的设计肯定是使用OOP,例如这个人有手,脚,眼睛瞪属性。而对这个人上厕所这个动作就会涉及到AOP,例如上厕所前的先确定一下拿没拿手纸等。要理解AOP就首先要理解什么是切面耦合(cross-cutting concerns)。例如有这样一个需求,要求为一个程序中所有方法名称以test开头的方法打印一句log,这个行为就是一个典型的cross-cutting场景。首先这个打印log和业务毫无关系,然后其处于分散在整个程序当中的各个模块,如果按照我们原始的方法开发,一旦后期需求变动将是及其繁琐的。所以我们就需要将这个切面耦合封装隔离,不要将其混入业务代码当中。

    例如在王二狗的案子中,我们希望在案子起诉后打印一句成功的log,如果不使用代理的话,我们是需要将log写在相应的业务逻辑里面的,例如王二狗诉讼类SecondDogWang里面的submit()方法中。使用了动态代理后,我们只需要在InvocationHandler 里面的invoke()方法中写就可以了,不会侵入业务代码当中,在以后的维护过程中对业务毫无影响,这是我们希望看到的。

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("submit"))
               System.out.println("案件提交成功,证据如下:"+ Arrays.asList(args));
        Object result=method.invoke(target,args);
        return result;
    }
    

    输出结果为:

    案件提交成功,证据如下:[工资流水在此]
    老板欠薪跑路,证据如下:工资流水在此
    铁证如山,马旭还牛翠花血汗钱
    

    所以AOP主要可以用于:日志记录,性能统计,安全控制,事务处理,异常处理等场景下。

    总结

    静态代理比动态代理更符合OOP原则,在日常开发中使用也较多。动态代理在开发框架时使用较多,例如大名鼎鼎的Spring

    最后希望王二狗和牛翠花他们可以顺利拿回自己的血汗钱。

    GitHub源码地址design-patterns

    展开全文
  • 轻松学,Java 中的代理模式动态代理

    万次阅读 多人点赞 2017-06-29 22:08:55
    前几天我写了《秒懂,Java 注解 (Annotation)你可以这样学》,因为注解其实算反射技术中的一部分,然后我想了一下,反射技术中还有个常见的概念就是动态代理,于是索性再写一篇关于动态代理的博文好了。...

    前几天我写了《秒懂,Java 注解 (Annotation)你可以这样学》,因为注解其实算反射技术中的一部分,然后我想了一下,反射技术中还有个常见的概念就是动态代理,于是索性再写一篇关于动态代理的博文好了。

    我们先来分析代理这个词。

    代理

    代理是英文 Proxy 翻译过来的。我们在生活中见到过的代理,大概最常见的就是朋友圈中卖面膜的同学了。

    她们从厂家拿货,然后在朋友圈中宣传,然后卖给熟人。

    这里写图片描述

    按理说,顾客可以直接从厂家购买产品,但是现实生活中,很少有这样的销售模式。一般都是厂家委托给代理商进行销售,顾客跟代理商打交道,而不直接与产品实际生产者进行关联。

    所以,代理就有一种中间人的味道。

    接下来,我们说说软件中的代理模式。

    代理模式

    代理模式是面向对象编程中比较常见的设计模式。
    这里写图片描述

    这是常见代理模式常见的 UML 示意图。

    需要注意的有下面几点:

    1. 用户只关心接口功能,而不在乎谁提供了功能。上图中接口是 Subject。
    展开全文
  • 代码实例 和装饰者区别 概念 为其他对象提供一种代理以控制这个对象的访问,在某些情况下一个对象不能直接访问那个对象时,代理就起到了客户端和被代理对象(委托类)中介作用。 代理类和委托类都有同样接口。 ...

    控制对象访问权限

    • 概念
    • 类图
    • 代码实例
    • 和装饰者区别

    概念

    为其他对象提供一种代理以控制这个对象的访问,在某些情况下一个对象不能直接访问那个对象时,代理就起到了客户端和被代理对象(委托类)中介作用。 代理类和委托类都有同样接口。

    好处:可以不用动原来类的逻辑,再次增加一些功能,符合开闭原则。真正的业务还是交给被代理对象处理的,因此在其委托被代理对象处理业务前后实现一些公共逻辑服务,例如加入缓存或日志等功能,无须修改原来的类就可以使用代理进行实现。

    类图

    在这里插入图片描述

    Subject: 代理类和被代理类实现同样的接口

    Proxy:代理类,里面有被代理类,具体逻辑委托被代理类进行处理

    RealSubject:被代理类,可以在其内做一些访问权限控制,额外的业务处理

    Client:看到的是代理类,并不知道具体处理业务逻辑的类,降低耦合性

    代码实例

    UserDAO 代理和被代理的公共的接口(Subject)

    /**
     * @author duanyimiao
     * @create 2018-09-22 10:47 AM
     * @description 用户数据持久化逻辑接口
     **/
    public interface UserDAO {
    
        boolean insert(String name,int age);
    }
    

    UserDAOImpl 被代理类(RealSubject)

    /**
     * @author duanyimiao
     * @create 2018-09-22 10:47 AM
     * @description 用户数据持久具体实现
     **/
    public class UserDAOImpl implements UserDAO {
    
        @Override
        public boolean insert(String name, int age) {
            System.out.println("insert to database name="+name +" age="+age);
            return true;
        }
    }
    

    UserDAOProxyByInterface 代理类,通过实现接口方式实现代理方式(Proxy)

    /**
     * @author duanyimiao
     * @create 2018-09-22 10:50 AM
     * @description 用户持久数据的代理类(和被代理类实现同个接口方式)
     **/
    public class UserDAOProxyByInterface implements UserDAO {
        private UserDAOImpl conreteUserDAO;
    
        public UserDAOProxyByInterface() {
    
        }
        public UserDAOProxyByInterface(UserDAOImpl conreteUserDAO) {
            this.conreteUserDAO = conreteUserDAO;
        }
        @Override
        public boolean insert(String name, int age) {
            System.out.println("before insert handle some logic by interface");
            return conreteUserDAO.insert(name, age);
        }
    }
    

    UserDAOProxyByExtend 代理类,通过继承被代理类实现的代理方式(Proxy)

    /**
     * @author duanyimiao
     * @create 2018-09-22 10:50 AM
     * @description 用户持久数据的代理类(继承被代理类方式)
     **/
    public class UserDAOProxyByExtend extends UserDAOImpl {
        private UserDAOImpl conreteUserDAO;
    
        public UserDAOProxyByExtend() {
    
        }
        public UserDAOProxyByExtend(UserDAOImpl conreteUserDAO) {
            this.conreteUserDAO = conreteUserDAO;
        }
        @Override
        public boolean insert(String name, int age) {
            System.out.println("before insert handle some logic by extend");
            return conreteUserDAO.insert(name, age);
        }
    }
    

    Client 获取代理对象客户端(Client)

    /**
     * @author duanyimiao
     * @create 2018-09-22 10:52 AM
     * @description
     **/
    public class Client {
        public static void main(String[] args) {
            UserDAOImpl conreteUserDAO = new UserDAOImpl();
            UserDAOProxyByInterface userDAOProxyByInterface = new UserDAOProxyByInterface(conreteUserDAO);
            //和被代理类实现同个接口方式进行代理
            userDAOProxyByInterface.insert("dynamo", 18);
    
            //通过继承被代理类方式进行代理
            UserDAOProxyByExtend userDAOProxyByExtend = new UserDAOProxyByExtend(conreteUserDAO);
            userDAOProxyByExtend.insert("dynamo", 18);
    
        }
    }
    

    输出结果:

    before insert handle some logic by interface
    insert to database name=dynamo age=18
    before insert handle some logic by extend
    insert to database name=dynamo age=18
    

    和装饰者模式区别

    代理模式关注的是控制对对象的访问,一般具体的被代理对象对Client是不可见的,直接在创建代理对象时就创建了被代理对象,也就是编译时就确定了。 但是装饰者模式:更关注的是在一个对象方法上动态添加修饰逻辑,但是这些逻辑修饰在运行时才能确定的,通过构造方法传入具体的装饰者对象,执行时递归调用修饰对象的方法。

    动态代理

    静态代理和动态代理:

    1、静态代理:代理类由程序员创建的然后编译成.class文件。但是其中缺点是,具有重复代码,灵活性不好,例如在执行接口A中所有方法之前加上日志逻辑,那么使用静态代理的话,在代理类中每个方法都得加,如果我想add* 开头方法加上一种逻辑,select* 开头方法加上另一种逻辑,那么就很难去实现和维护了,想解决以上困惑就要使用动态代理了。

    2、动态代理:是在运行的时候,通过jvm中的反射进行动态创建对象,生成字节码对象(构造方法参数 InvocationHandler h类型),传入由我们实现InvocationHandler接口的对象,通过反射创建代理对象。 然后当调用代理对象的任何方法都会调用h中的 invoke(Object proxy,Method method,Object[] args)传入当前代理对象、当前调用的方法、方法参数值。

    JDK动态代理实现原理

    要求被代理类必须要实现接口,因为JDK动代理实现是通过实现接口方式来实现的。需要实现 InvocationHandler接口(在invoke方法中实现一些额外的逻辑,添加一些新功能),通过Proxy.newProxyInstance(ClassLoader classLoader,Class<?> interfaces,InvocationHandler h)。

    实现步骤

    1.定义一个接口ProxyObj

    2.编写该接口I的实现类ProxyObjImpl

    3.编写InvocationHandler接口的实现类InvokcationInvokeHandler,构造h类对象的时候可以把要代理的对象target传入,target完成实际的动作。在里面的invoke方法里编写自己想实现的逻辑,然后再调用实际要完成的动作就可以。

    4.调用Proxy.newProxyInstance方法,传递的三个参数分别是代理类的类加载器(可以用Impl实例的getClass().getClassLoader())
    、代理类要实现的接口列表(可以用Impl实例getClass().getInterfaces())、InvocationHandler实现类的实例。

    这样就生成了 P r o x y 0 类 的 对 象 , 由 于 Proxy0类的对象,由于 Proxy0Proxy0类实现了ProxyObj接口,所以可以将对象强制转型成ProxyObj。

    再说一下Proxy.newProxyInstance方法的实际过程:

    1.使用传入的InvocationHandler实例参数将Proxy类的h实例初始化,注意,如果传入空对象的话,会抛出空指针错误,即h不能为空。

    2.运行时生成代理Class,即$Proxy0

    3.利用上面动态生成的$Proxy0类,构造出该类的对象,并返回。

    实现代码

    ProxyObj 代理类和被代理类实现的公共接口

    public interface ProxyObj {
    
     public  void setName(String name);
    }
    

    ProxyObjImpl 被代理类

    public class ProxyObjImpl implements  ProxyObj,ProxyObj1{
    
      private String name;
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        System.out.println("set name="+name);
        this.name = name;
      }
    
      @Override
      public void setAge(Integer age) {
        System.out.println("set age="+age);
      }
    }
    

    InvokcationInvokeHandler 实现InvocationHandler接口

    public class InvokcationInvokeHandler implements InvocationHandler {
        //真实的对象
        private ProxyObj proxyPbj;
    
        public InvokcationInvokeHandler(ProxyObj proxy) {
            this.proxyPbj = proxy;
        }
    
        /**
         *
         * @param proxy jvm生成的动态代理对象 $Proxy0
         * @param method 当前代理对象调用的方法对象,是代理对象实现接口中的方法
         * @param args 调用对象传入的参数
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before call set proxy" + proxy.getClass()+" method="+method+" args="+ Arrays.toString(args));
            method.invoke(proxyPbj, args);
            //((ProxyObj)proxy).setName("2"); 会导致invoke方法循环调用导致StackoverflowError
            return null;
        }
    }
    

    ProxyFactory 获取代理对象的工厂

    public class ProxyFactory {
    
      //获取代理对象
      public static ProxyObj getProxy(ProxyObj proxyObj) {
        /**
         * loader 指定加载jvm运行时动态生成的代理对象的加载器
         *
         * interface 真实对象实现的所有接口
         *
         * h 实现InvocationHandler接口对象
         */
        return (ProxyObj) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
            proxyObj.getClass().getInterfaces(), new InvokcationInvokeHandler(proxyObj));
      }
    
      public static void main(String[] args) {
        ProxyFactory.getProxy(new ProxyObjImpl()).setName("hh");
      }
    }
    

    输出结果

    before call set proxyclass com.sun.proxy.$Proxy0 method=public abstract void com.dynamo.proxy.dynamicproxy.jdk.ProxyObj.setName(java.lang.String) args=[hh]
    set name=hh
    

    流程图:

    在这里插入图片描述

    通过javap可以看到具体代理类为:

    import java.lang.reflect.InvocationHandler;   
    import java.lang.reflect.Method;  
    import java.lang.reflect.Proxy;   
    import java.lang.reflect.UndeclaredThrowableException;  
       
    public final class $Proxy0 extends Proxy implements UserManager {  
        private static Method m1;  
        private static Method m0;  
        private static Method m3;  
        private static Method m2;  
      
        static {  
            try {  
                m1 = Class.forName("java.lang.Object").getMethod("equals",  
                        new Class[] { Class.forName("java.lang.Object") });  
                m0 = Class.forName("java.lang.Object").getMethod("hashCode",  
                        new Class[0]);  
                m3 = Class.forName("cn.edu.jlu.proxy.UserManager").getMethod("addUser",  
                        new Class[0]);  
                m2 = Class.forName("java.lang.Object").getMethod("toString",  
                        new Class[0]);  
            } catch (NoSuchMethodException nosuchmethodexception) {  
                throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
            } catch (ClassNotFoundException classnotfoundexception) {  
                throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
            }  
        }  
      
        public $Proxy0(InvocationHandler invocationhandler) {  
            super(invocationhandler);  
        }  
      
        @Override  
        public final boolean equals(Object obj) {  
            try {  
                return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))  
                        .booleanValue();  
            } catch (Throwable throwable) {  
                throw new UndeclaredThrowableException(throwable);  
            }  
        }  
      
        @Override  
        public final int hashCode() {  
            try {  
                return ((Integer) super.h.invoke(this, m0, null)).intValue();  
            } catch (Throwable throwable) {  
                throw new UndeclaredThrowableException(throwable);  
            }  
        }  
      
        @Override  
        public final String toString() {  
            try {  
                return (String) super.h.invoke(this, m2, null);  
            } catch (Throwable throwable) {  
                throw new UndeclaredThrowableException(throwable);  
            }  
        }  
      
        @Override  
        public void addUser() {  
            try {  
                super.h.invoke(this, m3, null);  
                return;  
            } catch (Error e) {  
            } catch (Throwable throwable) {  
                throw new UndeclaredThrowableException(throwable);  
            }  
      
        }  
    } 
    
    

    为什么无论调用JDK的动态代理对象还是CGLIB的代理对象的toString方法会出现栈溢出?

    通过阅读JDK中代理类的源码 $Proxy0 extends Proxy implements I1,I2 看到,其中该代理类通过反射获取到这么几种Method对象, Object类中的方法对象:m2 = Class.forName(“java.lang.Object”).getMethod(“toString”,new Class[0]);
    除了toString,还有 equals 和 hashCode方法。

    还有在Proxy.newProxInstance()传入的Class[] interfaces 所有接口中的方法。当这些方法调用的时候都会触发父类Proxy中的InvocationHandler对象中的invoke方法

    ((String)super.h.invoke(this, m2, null));

    所以如果在 实现InvocationHandler对象中的invoke方法中 调用代理对象中的 toString hashCode equals 和 其中被代理类的方法时都会导致栈溢出。
    从上述的流程和代码可以看到如果调用代理类中的toString equals hashCode 和实现被代理类方法时都会导致方法栈溢出。

    CGLIB动态代理实现原理

    CGLIB(Code Generation Library)实现动态代理,并不要求被代理类必须实现接口,底层采用asm字节码生成框架生成代理类字节码(该代理类继承了被代理类)。所以被代理类一定不能定义为final class并且对于final 方法不能被代理。

    实现步骤

    Ehancer enhancer = new Enhancer() //Enhancer为字节码增强器,很方便对类进行扩展
    enhancer.setSuperClass(被代理类.class);
    enhancer.setCallback(实现MethodInterceptor接口的对象)
    enhancer.create()//返回代理对象,是被代理类的子类
    

    MethodInterceptor接口的intercept方法

    /**
    *obj 代理对象
    *method 委托类方法
    *arg 方法参数
    *MethodProxy 代理方法MethodProxy对象,每个方法都会对应有这样一个对象 
    *通过methodProxy.invokeSuper(obj,arg)方法调用委托类的方法
    */
    public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy)
    

    实现代码

    Query 被代理类

    /**
     * @author duanyimiao
     * @create 2018-09-22 11:12 AM
     * @description 被代理类
     **/
    public class Query {
    
        public boolean query(String name){
            System.out.println("Query query"+name);
            return true;
        }
    
        /**
         * cglib 代理通过继承被代理类,所有final方法不能被重写,所以定义的final方法不能被代理
         * @param name
         * @return
         */
        public final  boolean query1(String name){
            System.out.println("Query query1"+name);
            return true;
        }
    }
    

    CglibProxy 方法拦截器

    /**
     * @author duanyimiao
     * @create 2018-09-22 11:04 AM
     * @description 目标方法拦截,在进行具体业务逻辑前后做一些额外逻辑
     **/
    public class CglibProxy implements MethodInterceptor {
    
        /**
         *cglib代理是通过继承被代理类的方式进行代理的
         *
         * @param o 目标实例对象(继承于传入的被代理类)
         * @param method 目标方法对象
         * @param args 方法参数
         * @param proxy 代理对象实例
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            //o.toString o.equals o.hashCode方法调用都会导致方法栈溢出
            System.out.println("o="+o.getClass()+" method="+method+" args="+ Arrays.toString(args)+" proxy="+proxy);
            System.out.println("before call add extera logic");
            //调用父类(被代理类)的方法
            boolean result = ((Boolean) proxy.invokeSuper(o,args)).booleanValue();
            System.out.println("after call add extera logic");
            return result;
        }
    }
    

    CglibProxyFactory 产生代理对象的工厂

    /**
     * @author duanyimiao
     * @create 2018-09-22 11:04 AM
     * @description
     **/
    public class CglibProxyFactory {
        private Enhancer enhancer = new Enhancer();
    private CglibProxy cglibProxy = new CglibProxy();
        public Object getProxyObject(Class cls) {
            enhancer.setSuperclass(cls);
            enhancer.setCallback(cglibProxy);
            return enhancer.create();
        }
    }
    

    Client 获取代理对象的Client

    /**
     * @author duanyimiao
     * @create 2018-09-22 11:18 AM
     * @description
     **/
    public class Client {
        public static void main(String[] args) {
            CglibProxyFactory cglibProxyFactory = new CglibProxyFactory();
            Query query = (Query)cglibProxyFactory.getProxyObject(Query.class);
            query.query("dynamo");
            //该方法不能进过代理对象,因为query1方法定义为final,因此不能被代理类重写,因此直接调用被代理类的query1方法
            query.query1("dynamo1");
        }
    }
    

    流程图

    在这里插入图片描述

    cglib动态生成的代理类

    import java.lang.reflect.Method;
    import net.sf.cglib.core.ReflectUtils;
    import net.sf.cglib.core.Signature;
    import net.sf.cglib.proxy.Callback;
    import net.sf.cglib.proxy.Factory;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class HelloServiceImpl$$EnhancerByCGLIB$$82ef2d06
      extends HelloServiceImpl
      implements Factory
    {
      private boolean CGLIB$BOUND;
      private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
      private static final Callback[] CGLIB$STATIC_CALLBACKS;
      private MethodInterceptor CGLIB$CALLBACK_0;
      private static final Method CGLIB$sayHello$0$Method;
      private static final MethodProxy CGLIB$sayHello$0$Proxy;
      private static final Object[] CGLIB$emptyArgs;
      private static final Method CGLIB$finalize$1$Method;
      private static final MethodProxy CGLIB$finalize$1$Proxy;
      private static final Method CGLIB$equals$2$Method;
      private static final MethodProxy CGLIB$equals$2$Proxy;
      private static final Method CGLIB$toString$3$Method;
      private static final MethodProxy CGLIB$toString$3$Proxy;
      private static final Method CGLIB$hashCode$4$Method;
      private static final MethodProxy CGLIB$hashCode$4$Proxy;
      private static final Method CGLIB$clone$5$Method;
      private static final MethodProxy CGLIB$clone$5$Proxy;
      
      static void CGLIB$STATICHOOK1()
      {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class localClass1 = Class.forName("proxy.HelloServiceImpl$$EnhancerByCGLIB$$82ef2d06");
        Class localClass2;
        Method[] tmp95_92 = ReflectUtils.findMethods(new String[] { "finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (localClass2 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$finalize$1$Method = tmp95_92[0];
        CGLIB$finalize$1$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "finalize", "CGLIB$finalize$1");
        Method[] tmp115_95 = tmp95_92;
        CGLIB$equals$2$Method = tmp115_95[1];
        CGLIB$equals$2$Proxy = MethodProxy.create(localClass2, localClass1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        Method[] tmp135_115 = tmp115_95;
        CGLIB$toString$3$Method = tmp135_115[2];
        CGLIB$toString$3$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        Method[] tmp155_135 = tmp135_115;
        CGLIB$hashCode$4$Method = tmp155_135[3];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(localClass2, localClass1, "()I", "hashCode", "CGLIB$hashCode$4");
        Method[] tmp175_155 = tmp155_135;
        CGLIB$clone$5$Method = tmp175_155[4];
        CGLIB$clone$5$Proxy = MethodProxy.create(localClass2, localClass1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
        tmp175_155;
        Method[] tmp223_220 = ReflectUtils.findMethods(new String[] { "sayHello", "()V" }, (localClass2 = Class.forName("proxy.HelloServiceImpl")).getDeclaredMethods());
        CGLIB$sayHello$0$Method = tmp223_220[0];
        CGLIB$sayHello$0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "sayHello", "CGLIB$sayHello$0");
        tmp223_220;
        return;
      }
      
      final void CGLIB$sayHello$0()
      {
        super.sayHello();
      }
      
     	public final void sayHello()
    	  {
    	    MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
    	    if (tmp4_1 == null)
    	    {
    	      tmp4_1;
    	      CGLIB$BIND_CALLBACKS(this);
    	    }
    	    if (this.CGLIB$CALLBACK_0 != null) {
    	     tmp17_14.intercept(this, CGLIB$sayHello$3$Method, CGLIB$emptyArgs, CGLIB$sayHello$3$Proxy);
    	    }
    	    super.sayHello();
    	  }
      
      final void CGLIB$finalize$1()
        throws Throwable
      {
        super.finalize();
      }
      
      protected final void finalize()
        throws Throwable
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        if (this.CGLIB$CALLBACK_0 != null) {
          return;
        }
        super.finalize();
      }
      
      final boolean CGLIB$equals$2(Object paramObject)
      {
        return super.equals(paramObject);
      }
      
      public final boolean equals(Object paramObject)
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null)
        {
          Object tmp41_36 = tmp17_14.intercept(this, CGLIB$equals$2$Method, new Object[] { paramObject }, CGLIB$equals$2$Proxy);
          tmp41_36;
          return tmp41_36 == null ? false : ((Boolean)tmp41_36).booleanValue();
        }
        return super.equals(paramObject);
      }
      
      final String CGLIB$toString$3()
      {
        return super.toString();
      }
      
      public final String toString()
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null) {
          return (String)tmp17_14.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy);
        }
        return super.toString();
      }
      
      final int CGLIB$hashCode$4()
      {
        return super.hashCode();
      }
      
      public final int hashCode()
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null)
        {
          Object tmp36_31 = tmp17_14.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
          tmp36_31;
          return tmp36_31 == null ? 0 : ((Number)tmp36_31).intValue();
        }
        return super.hashCode();
      }
      
      final Object CGLIB$clone$5()
        throws CloneNotSupportedException
      {
        return super.clone();
      }
      
      protected final Object clone()
        throws CloneNotSupportedException
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null) {
          return tmp17_14.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy);
        }
        return super.clone();
      }
      
      public static MethodProxy CGLIB$findMethodProxy(Signature paramSignature)
      {
        String tmp4_1 = paramSignature.toString();
        switch (tmp4_1.hashCode())
        {
        case -1574182249: 
          if (tmp4_1.equals("finalize()V")) {
            return CGLIB$finalize$1$Proxy;
          }
          break;
        }
      }
      
      public HelloServiceImpl$$EnhancerByCGLIB$$82ef2d06()
      {
        CGLIB$BIND_CALLBACKS(this);
      }
      
      public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback)
      {
        CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
      }
      
      public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback)
      {
        CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
      }
      
      private static final void CGLIB$BIND_CALLBACKS(Object paramObject)
      {
        82ef2d06 local82ef2d06 = (82ef2d06)paramObject;
        if (!local82ef2d06.CGLIB$BOUND)
        {
          local82ef2d06.CGLIB$BOUND = true;
          Object tmp23_20 = CGLIB$THREAD_CALLBACKS.get();
          if (tmp23_20 == null)
          {
            tmp23_20;
            CGLIB$STATIC_CALLBACKS;
          }
          local82ef2d06.CGLIB$CALLBACK_0 = (// INTERNAL ERROR //
    

    其中该代理会实现所有被代理类非final的方法,并且每个方法有两种形式:例如被代理类有sayHello()方法,那么代理类会有两个该方法

    final void CGLIB$sayHello$0()//该方法是通过在MethodInterceptor对象中methodProxy.invokeSuper(obj,args)进行调用的
      {
        super.sayHello();
      }
    
    public final void sayHello()
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        if (this.CGLIB$CALLBACK_0 != null) {
         tmp17_14.intercept(this, CGLIB$sayHello$3$Method, CGLIB$emptyArgs, CGLIB$sayHello$3$Proxy);
        }
        super.sayHello();
      }
    

    一个是重写了父类的sayHello方法,如果callback不为null就会调用 其中实现MethodInterprector接口的对象的invoke方法。

    实现MethodInterceptor接口的实例的intercept方法

        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            //o.toString o.equals o.hashCode方法调用都会导致方法栈溢出
            System.out.println("o="+o.getClass()+" method="+method+" args="+ Arrays.toString(args)+" proxy="+proxy);
            System.out.println("before call add extera logic");
            //调用父类(被代理类)的方法
            boolean result = ((Boolean) proxy.invokeSuper(o,args)).booleanValue();
            System.out.println("after call add extera logic");
            return result;
        }
    

    代理类为每个委托方法都会生成两个方法
    在这里插入图片描述

    其中如果想要调用被代理类中的方法就需要使用 methodProxy.invokeSuper(obj,arg) 其中每个父类中非final的方法都会对应一个MethodProxy对象,下面看看其中该类中的invokeSuper方法:

    在这里插入图片描述

    和JDK动态代理最大区别就是,JDK是通过反射进行调用被代理对象的方法,而cglib是直接对被代理方法进行调用的。 通过类FastClassInfo存放了该被代理类和代理类对象,f1指向委托类对象,f2指向代理类对象,i1和i2分别代表着sayHello方法以及CGLIB$sayHello$0方法在类信息数组中的下标。其中

    在这里插入图片描述

    FastClass对Class对象进行特别的处理,比如将会用数组保存method的引用,每次调用方法的时候都是通过一个index下标来进行对类中某个方法调用。其中FastClassInfo中的f1、f2 i1、i2通过init方法进行初始化的,i1 和 i2是通过MethodProxy的getIndex方法就是通过方法签名来获得方法在存储了Class信息的数组中的下标。

    在这里插入图片描述

    从上面的源码分析可以看到invokeSuper方法调用实际上就是调用代理类的CGLIB$sayHello$0()方法然后该方法又调用其父类的sayHello方法。

    代理方式

    1、远程代理

    例如:客户端有个接口A 里面有多种方法,客户端想和通过接口A和服务端通讯,给服务端发送请求。客户端并不需要知道实现A接口具体实现,只管调用就行,和请求本地接口一样。 这里A接口的实现就可以看作访问服务端的代理。这个代理就帮你发送请求了,并获取结果吐给客户端。

    2、虚拟代理

    例如浏览器加载大图片时会很慢,加载文字就很快。所以通过虚拟代理进行优化,代理对象会记录下图片的url和尺寸,然后一并返回未加载出来图片,等到访问到该图片的位置再去请求该页面。这个时候就不会出现下面的加载很快的文字一直等待上面图片加载出来才显示。

    3、安全代理

    在访问具体对象的时候做一些权限的校验,这样更好的控制对象的访问。

    4、智能指引

    在访问真实对象时候做一些额外逻辑处理,例如记录对象访问次数和引用次数,该对象第一次访问加入缓存中,在访问一个实际对象前,检查是否已经锁定它。

    展开全文
  • 此资源为文章中《代理设计模式:静态代理动态代理的理解、实现与区别(优缺点)》与《 AOP动态代理声明式的3种配置方式过程与区别》的案例代码,可下载参考学习。
  • 动态代理的两种实现方式

    千次阅读 多人点赞 2019-10-15 18:41:48
    1.动态代理概述 ...代理模式动态代理需要使用专门的API来产生代理对象. 动态代理应用场景:在不想或不能够修改目标对象的情况下,对其进行功能增强 2. 常用的动态代理技术 2.1 jdk动态代理 jdk...
  • 代理模式 * 概念: 1. 真实对象:被代理的对象 2. 代理对象: 3. 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的 * 实现方式: 1. 静态代理:有一个类文件描述代理模式 2. 动态代理:在内存中...
  • 主要介绍了Java动态代理模式简单案例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Java设计模式-之代理模式(动态代理)

    千次阅读 2017-09-10 15:47:17
    1、什么叫代理模式: &amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;...
  • Java各种代理模式以及AOP的实现代码 : 1.AspectJ - 静态代理 2. 动态代理 (1)JDK动态代理 (2)CGlib代理
  • 深入理解代理模式:静态代理与JDK动态代理

    万次阅读 多人点赞 2018-03-01 00:22:11
     代理模式为其他对象提供了一种代理以控制对这个对象的访问,具体实现包括两大类:静态代理和动态代理。Java动态代理机制的出现使得Java开发人员只需要简单地指定一组接口及委托类对象便能动态地获得代理类,并且其...
  • 10分钟看懂动态代理设计模式

    万次阅读 多人点赞 2018-03-14 10:38:00
    原文作者:欧阳锋点击打开链接动态代理是Java语言中非常经典的一种设计模式,也是所有设计模式中最难理解的一种。本文将通过一个简单的例子模拟JDK动态代理实现,让你彻底明白动态代理设计模式的本质,文章中可能会...
  • 代理模式(Proxy Pattern)是一个使用频率非常高的设计模式,其定义如下:Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问)。...
  • 代理模式及简单Java案例代码实现

    千次阅读 2018-05-25 17:02:27
    1.代理模式概述: 代理模式属于结构型模式,指的是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用...
  • 文章目录1 引子2 业务场景介绍3 静态代理模式4 装饰器模式5 动态代理模式 1 引子 看过上篇文章《【Mybatis源码探索】 — Mybatis查询过程核心源码解读 — 先聊聊selectOne方法》对Executor和StatementHandler的...
  • 代理模式动态代理模式

    千次阅读 多人点赞 2015-03-19 09:35:14
    1、代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。 代理模式给某...
  • c#动态代理

    2019-01-13 21:12:17
    c#动态代理核心代码,通过.netframe work 提供的realproxy类实现动态代理模式
  • 狂神说Spring06:静态/动态代理模式

    千次阅读 多人点赞 2020-04-21 10:22:56
    狂神说Spring系列连载课程,通俗易懂,基于Spring最新版本,欢迎各位狂粉转发关注学习。禁止随意转载,转载记住贴出B站视频链接及公众号链接!代理模式为什么要学习代理模式,因为AOP...
  • 代理模式动态代理是学习AOP的基础
  • Java设计模式模式---动态代理模式

    千次阅读 2018-08-15 21:48:15
    代理模式 代理模式的意图是通过一个接口或者占位符来控制对该对象的访问 代理对象通常拥有一个和真实对象相同的接口,通过控制访问将请求合理的转发给底层真实的对象 动态代理(需要代理的类实现了接口) 通过...
  • 自己编写的设计模式示例,绝对不含伪代码,示例简单易懂 适合初学者学习使用
  • Java JDK 动态代理实现和代码分析

    千次阅读 2021-06-02 20:51:44
    代理模式2. 为什么要使用动态代理3. JDK 动态代理简单结构图4. JDK 动态代理实现步骤5. JDK 动态代理 API5.1 java.lang.reflect.Proxy5.1 java.lang.reflect.InvocationHandler二、JDK 动态代理的实现(代码)1. ...
  • Android 动态代理以及利用动态代理实现 ServiceHook

    万次阅读 多人点赞 2017-02-25 20:44:15
    以上就是动态代理模式的最简单实现代码,JDK 通过使用 java.lang.reflect.Proxy 包来支持动态代理,我们来看看这个类的表述: Proxy provides static methods for creating dynamic proxy classes and...
  • 面试中关于Spring AOP和代理模式的那些事

    万次阅读 多人点赞 2018-12-09 23:00:16
    我们知道,Spring 中 AOP 是一大核心技术,也是面试中经常会被问到的问题,最近我在网上也看到很多面试题,其中和 Spring AOP 相关的就有...谈谈你对代理模式的理解? 静态代理和动态代理有什么区别? 如何实现动态...
  • 工厂模式 代码实现: 步骤一:创建一个接口 Car.java package FactoryMode; public interface Car { public void run(); } 步骤二:创建实现类 BaoMaCar.java package FactoryMode; public class BaoMaCar ...
  • 动态代理与装饰器模式的区别

    千次阅读 2017-03-29 21:11:54
    这里,假设大家已经基本了解动态代理与装饰器模式。 我们知道增强一个类的功能而不改变这个类的源码,我们可以有动态代理和装饰器模式这两种办法。(本文讨论的区别只是基于增强类功能的区别) 那么我们该如何选择呢...
  • 我们都知道SpringAOP是用代理模式实现,那么到底是如何实现的呢?我们来探一探究竟,并手写部分代码。 定义 代理模式(Proxy Pattern):是指为其他对象提供一种代理、来控制这个对象的访问。 代理对象在客户端和...
  • 代理模式: 代理是基本的设计模式之一,它为你提供额外的或者不同的操作,而插入的用来代理"实际"对象的对象.这些操作通常涉及与"实际"对象的通信,因此代理通常充当着中间人的角色. 动态代理 动态代理是在实现阶段...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 339,890
精华内容 135,956
关键字:

动态代理模式代码