Java基础-静态代理以及动态代理

动态代理:

在了解动态代理之前,先对代理有一个认识.

代理模式是Java常见的设计模式之一。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。

打个比方:你买火车票的时候,并不直接花钱购买, 而是将钱预先垫付到抢票软件上, 使抢票软件为你购买, 你要做的行为就是买票,抢票软件就是你的代理

代理对象控制对被代理对象的访问:

这是代理的通用模型图

  • Subject:定义了被代理角色和代理角色的共同接口或者抽象类,也就是subject中定义了共同接口opration();
  • Realsubject:实现或者继承抽象主题角色,定义实现具体业务逻辑的实现。
  • Proxy:也就是代理人,porxy持有Realsubject的引用控制和实现. 并且有自己的处理逻辑.

代理分为静态和动态两种,先了解静态代理,知道其缺点后,再了解动态代理,会豁然开朗.

静态代理的作用:

静态代理通常用于对原有业务逻辑的扩充。比如持有二方包的某个类,并调用了其中的某些方法。然后出于某种原因,比如记录日志、打印方法执行时间,但是又不好将这些逻辑写入二方包的方法里。所以可以创建一个代理类实现和二方方法相同的方法,通过让代理类持有真实对象,然后在原代码中调用代理类方法,来达到添加我们需要业务逻辑的目的。

静态代理的实现:

这里方便理解 引入的Proxy是自己定义的,在下面动态代理的时候会使用java.reflect中提供的Proxy

package proxy;
//将业务层抽象出来的接口.
public interface Subject {
    void doSomething();
}
package proxy;

//真实对象,也就是被代理者,理解为你自己就可以了,要进行买票行为.
public class RealObject implements Subject{

    @Override
    public void doSomething() {

        System.out.println("这里是真实对象");

    }
}
package proxy;

//代理者,进行代理事务的人,理解成抢票软件,要代替你进行买票行为.
public class Proxy implements  Subject{

    private Subject realObject;

     Proxy(Subject realObject){
        this.realObject=realObject;
        //从这里知道需要代理的人是谁
    }

    @Override
    public void doSomething() {
        System.out.println("这里是代理对象");
        //可以在调用真实对象前增加操作
        //例如在开抢前告诉你,抢票要开始了.
        realObject.doSomething();//在这里调用真实的代理对象
        //可以在调用真实对象后增加操作.
        //在抢票结束后,告诉你成功或者失败.
    }

}

执行:

package proxy;

public class ProxyTest {

    public static void main(String[] args){

        RealObject realObject =new RealObject();
        realObject.doSomething();//被代理对象做的事,或者说委托人想要做的事

        System.out.println("-----------------");
        Proxy proxy =new Proxy(new RealObject());//告知代理对象被代理对象是谁,或者说告诉执行者委托人要做什么.
        proxy.doSomething();//通过代理对象调用被代理对象,实现代理.

        /*
        代理和被代理是不是有点晕,换一种说法来说.
        以DOTA为例:
        大哥本来要自己拉野,忽然发现一大波线袭来,于是就和酱油说,帮我拉两波野,一会带你喝汤! 大哥就是被代理者
        酱油说: 是大哥! 酱油在去拉野的路上,吃了赏金符,拉完野之后配合队友杀了一波人. 酱油就是代理者
        吃赏金符就是预处理.
        杀人就是结果处理.
         */
    }

}

大家有没有发现,这样虽然形成了代理行为,但是写法恨死,耦合度很高,现在是一个火车票,如果有飞机票,演唱会票等等一系列的需求和一系列的雇主,会导致代理类的代码量越来越大,并且会有重名的危险,这也就是静态代理的缺点.

为了解决这个问题,大佬们发明出了动态代理的方法.

JAVA为我们提供了动态代理的接口,使用起来非常方便,下边来了解一下.

需要将要扩展的功能写在一个InvocationHandler 实现类里:

这个Handler中的invoke方法中实现了代理类要扩展的公共功能。

静态代理的缺点:

有十个不同的RealObject,同时我们要去代理的方法是不同的,比要代理方法:doSomething、doAnotherThing、doTwoAnotherThing.

方法1:为每个代理创建代理类,这样会造成数个类

方法2: 在一个代理类中创建数个代理方法,当代理方法越来越多的时候容易造成代理类中的代码量越来越大 并且有重名的风险.

为此动态代理诞生了:

动态代理的使用:

先看一下动态代理的接口:

  1. 实现InvocationHandler接口

我们来看一下接口的结构:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
//这个接口只有一个方法 就是invoke方法,也就是说我们只要实现invoke方法就可以了
}

虽然这个参数不用我们传入,但是还是需要了解一下,第一个就是代理类的实例,第二个是方法, 第三个是对象的参数数组.

2.通过newProxyInstance方法创建代理实例:

newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 

通过这个方法返回我们代理类的实例, 也就是RealObject的Proxy

返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序

从参数上看 第一个参数是类加载器, 第二个方法是个Class对象数组接口,第三个参数是我们上边实现的InvocationHandler

在这里不贴源码了,有兴趣的可以自己追踪或者查看下方我的参考资料.

动态代理实例:

沿用上边静态代理的类,下面只写测试类和处理类.

处理类:

import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicProxyHandler implements InvocationHandler {

    private Object realObject;

    Object bind(Object realObject){

        this.realObject=realObject;//给真实对象赋值

        return    Proxy.newProxyInstance(realObject.getClass().getClassLoader(),
                                       realObject.getClass().getInterfaces(),
                                        this);
        //通过Class对象得到该对象的构造器,接口方法数组,传入自己构造后的实例.
        //java.reflect.Proxy方法最后返回的是一个代理实例.
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在这里拓展代理逻辑

        System.out.println("rua!");

        Object result= method.invoke(realObject,args);//方法的调用.
        //这里的invoke调用是java进行调用,proxy对象,方法,和参数数组已经是我们之前传入的被代理类的了.

        return result;
    }
}

测试类:

public class DynamicProxy {

    public static void main(String[] args){

        DynamicProxyHandler pHandler=new DynamicProxyHandler();//创建我们动态代理处理类的对象
        Subject proxy=(Subject)pHandler.bind(new RealObject());//对其进行动态代理的参数绑定然后返回一个代理实例
        proxy.doSomething();//调用
    }
}

我第一次看的时候也是云里雾里,不明白为什么这样就动态了, 这里的方法调用,都与方法对象无关,不直接进行调用.

不管你在Subject中定义了什么接口,都与调用无关,依靠反射,实时获取你的方法,参数,类的数据,再通过反射进行调用.

有十个不同的RealObject,同时我们要去代理的方法是不同的,比要代理方法:doSomething、doAnotherThing、doTwoAnotherThing.

以这个例子来说, 我传入10个不同的对象,对象中自然有自己的实现,我通过反射拿到实现后构建新的对象,不会对原有对象造成影响,再对新的对象进行方法调用操作,来100个 1000个对象也同样可以.

上面一切的条件都是建立在反射的基础上,如果反射了解的不太清楚,请返回去看反射,我的博客也有写,也可以通过网络自行了解.

参考资料:

1.https://blog.csdn.net/wangqyoho/article/details/77584832

2.https://www.zhihu.com/question/20794107/answer/23330381

3.Thinking in java page 592-598

原文地址:https://www.cnblogs.com/Curry-Rice/p/8990904.html

时间: 2024-08-09 01:38:37

Java基础-静态代理以及动态代理的相关文章

Java基础之反射和动态代理

1,反射是依赖于Class对象,然后根据Class对象,去操作该类的资源的.Class对象是发射的基石! 问题1:人这类事物用什么表示?汽车这类事物用什么表示>计算机文件用什么表示?有如此多的事物该用什么表示? 答案:Person类,Car类,File类,这么多的类也是一类事物,这类事物用Class表示. 问题2:Person类的对象,我们知道代表一个具体的人.那么Class类的对象,又代表什么? 一个类,在硬盘上表示一个.class文件,JVM启动的时候,把文件加载到内存上,占用一片空间,称为

JAVA学习篇--静态代理VS动态代理

本篇博客的由来,之前我们学习大话设计,就了解了代理模式,但为什么还要说呢? 原因: 1,通过DRP这个项目,了解到了动态代理,认识到我们之前一直使用的都是静态代理,那么动态代理又有什么好处呢?它们二者的区别是什么呢? 2,通过学习动态代理了解到动态代理是一种符合AOP设计思想的技术,那么什么又是AOP? 下面是我对它们的理解! 代理Proxy: Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对

java 代理模式(静态代理、动态代理、Cglib代理) 转载

Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法 代理模式最大的特点就是代理类和实际业务类实现同一个接口(或继承同一父类),代理对象持有一个实际对象的引用,外部调用时操作的是代理对象,而在代理对象的内部实现中又会去调

java中静态代理和动态代理

一.概述 代理是一种模式,提供了对目标对象的间接访问方式,即通过代理访问目标对象.如此便于在目标实现的基础上增加额外的功能操作,前拦截,后拦截等,以满足自身的业务需求,同时代理模式便于扩展目标对象功能的特点也为多人所用. 按照代理的创建时期,代理类可以分为两种: 静态:由程序员创建代理类或特定工具自动生成源代码再对其编译.在程序运行前代理类的.class文件就已经存在了. 动态:在程序运行时运用反射机制动态创建而成. 我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理.如果我们在代码编

深入浅出java静态代理和动态代理

首先介绍一下,什么是代理: 代理模式,是常用的设计模式.特征是,代理类与委托类有相同的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类.以及事后处理消息. 代理类和委托类,存在着关联关系.代理类的对象本身并不真正实现服务,知识通过调用委托类的对象的相关方法. 代理类可以分为两种:静态代理和动态代理. 静态代理: 代理类是由程序员创建,或由工具生成的代码 编译成的.在程序运行前,代理类的 *.class文件已经存在了.直接就可以运行 . 动态代理: 动态代理的代理类.没有直接由

java静态代理与动态代理

原文链接:http://www.orlion.ga/207/ 一.代理模式 代理模式是经常用到的设计模式,代理模式是给指定对象提供代理对象.由代理对象来控制具体对象的引用. 代理模式涉及到的角色: 抽象主题角色:声明了代理主题和真实主题的公共接口,使任何需要真实主题的地方都能用代理主题代替. 代理主题角色:含有真实主题的引用,从而可以在任何时候操作真实主题,代理主题功过提供和真实主题相同的接口,使它可以随时代替真实主题.代理主题通过持有真实主题的引用,不但可以控制真实主题的创建或删除,可以在真实

【Java】代处理?代理模式 - 静态代理,动态代理

>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算,见[Java]Float计算不准确) package com.nicchagil.study.java.demo.No09代理.No01不用代理; import java.math.BigDecimal; public class FloatCalculator { public float add(fl

java静态代理与动态代理简单分析

原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理,静态代理是在编译时就将接口.实现类.代理类一股脑儿全部手动完成,但如果我们需要很多的代理,每一个都这么手动的去创建实属浪费时间,而且会有大量的重复代码,此时我们就可以采用动态代理,动态代理可以在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能. 其实方法直接调用就可以完成功能,为什么

【java项目实战】代理模式(Proxy Pattern),静态代理 VS 动态代理

这篇博文,我们主要以类图和代码的形式来对照学习一下静态代理和动态代理.重点解析各自的优缺点. 定义 代理模式(Proxy Pattern)是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用. 代理模式不会改变原来的接口和行为,仅仅是转由代理干某件事,代理能够控制原来的目标,比如:代理商,代理商仅仅会买东西,但并不会改变行为.不会制造东西. 让我们通过以下的代码好好理解一下这句话. 分类 静态代理和动态代理 静态代理 静态代理类图 代码演示样例 接口 pac