引言:

代理是基本的设计模式之一,它为你提供额外的或不同的操作而插入的用来代替实际对象的对象(委托对象)。这些对象通常涉及到与实际对象的通信,因此代理通常充当中间人的角色。--JAVA编程思想

相关的类和接口

要了解 Java 动态代理的机制,首先需要了解以下相关的类或接口:

  • java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。

    清单 1. Proxy 的静态方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
    static InvocationHandler getInvocationHandler(Object proxy)
     
    // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
    static Class getProxyClass(ClassLoader loader, Class[] interfaces)
     
    // 方法 3:该方法用于判断指定类对象是否是一个动态代理类
    static boolean isProxyClass(Class cl)
     
    // 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
    static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
        InvocationHandler h)
  • java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
    清单 2. InvocationHandler 的核心方法
    1
    2
    3
    // 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象
    // 第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
    Object invoke(Object proxy, Method method, Object[] args)

    每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象(参见 Proxy 静态方法 4 的第三个参数)。

  • java.lang.ClassLoader:这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中

    每次生成动态代理类对象时都需要指定一个类装载器对象(参见 Proxy 静态方法 4 的第一个参数)

这里有几点需要重点强调一下:

  • 从定义的方法可以看出代理类的出现是为了更加灵活的控制委托类方法的调用,而且做到无倾入;最终实现了一部分自己的逻辑后还是会调用委托类的方法调用,只不过在委托类调用之前或之后多了种控制
  • 未指定代理类的非限定名称。但是,以字符串 "$Proxy" 开头的类名空间应该为代理类保留
  • static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
        InvocationHandler h)该生成的动态代理类实例中,类装载器需要说明的是它和静态代理的区别,静态代理是编译阶段实现已经确定的代理类的.class文件已经生成。但动态代理是字节码是由JVM在运行态动态生成的。
以下是笔者实现的代码DEMO;供参考:

/**
*先是静态代理
*/
public interface MyInterface { void doSomeThing(); void someThingElse(String param);
}
public class RealObject implements MyInterface{

    @Override
public void doSomeThing() {
// TODO Auto-generated method stub
print("开始调用doSomeThing方法"); } @Override
public void someThingElse(String param) {
// TODO Auto-generated method stub
print("开始调用somethingelse 方法;参数"+param); } }
public class SimpleProxy implements MyInterface{

    private MyInterface myInterface;

    public SimpleProxy(MyInterface myInterface) {
this.myInterface=myInterface;
} @Override
public void doSomeThing() {
// TODO Auto-generated method stub
print("业务逻辑dosomething...");
myInterface.doSomeThing(); } @Override
public void someThingElse(String param) {
// TODO Auto-generated method stub
print("业务逻辑ELse...");
myInterface.someThingElse(param); } public static void consumer(MyInterface myInterface) { myInterface.doSomeThing();
myInterface.someThingElse("bubu..");
} public static void main(String[] args) {
consumer(new RealObject());
consumer(new SimpleProxy(new RealObject()));
} }

/**

*动态代理

*/

自定义一个调用处理器:

/**
* 调用处理器<P>
* 动态代理能把所有调用都重定向到调用处理器上
*/
public class DynamicProxyHandle implements InvocationHandler{ private Object proxied; public DynamicProxyHandle(Object object) {
this.proxied=object;
} @Override
public Object invoke(Object proxy,Method method,Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
print("proxy class:"+proxy.getClass()+" method:"+method+" args:"+args); if(method.getName().equals("doSomeThing")) {
print("代理检测到doSomeThing被调用");
}
// if(args!=null) {
// for(Object object:args) {
// print("====="+object);
// }
// } return method.invoke(proxied, args);
} }
public class SimpleDynamicProxy {

    public static void consumer(MyInterface myInterface) {

        myInterface.doSomeThing();
myInterface.someThingElse("bubu..");
} public static void main(String[] args) {
RealObject realObject = new RealObject(); consumer(realObject);
print("-----------------------------------------");
/**
* 1.一个类加载器【你通常可以从已经被加载的类对象中获取得到其类加载器,然后传递给它】
* 2.希望该代理实现的接口列表【不是类或抽象类】
* 3.以及InvocationHandler的一个实现(一个调用处理器)
*/
MyInterface dynamicProxy = (MyInterface) Proxy.newProxyInstance(MyInterface.class.getClassLoader(),
new Class[]{MyInterface.class}, new DynamicProxyHandle(realObject));
consumer(dynamicProxy); }
}

java有关静态代理及动态代理的实现的更多相关文章

  1. java静态代理与动态代理

    原文链接:http://www.orlion.ga/207/ 一.代理模式 代理模式是经常用到的设计模式,代理模式是给指定对象提供代理对象.由代理对象来控制具体对象的引用. 代理模式涉及到的角色: 抽 ...

  2. java的静态代理和动态代理(jdk、cglib)

    一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ...

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

    >不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...

  4. Java:静态代理 and 动态代理

    代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...

  5. Java基础-静态代理与动态代理比较

    JAVA的静态代理与动态代理比较 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.动态代理类: 在程序运行时,运用反射机制动态创建 ...

  6. java中静态代理,动态代理知识的补充

    文章转载自:http://blog.csdn.net/jialinqiang/article/details/8950989 一.Java动态代理 相对于静态代理的代理类在编译时生成(.class文件 ...

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

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理 ...

  8. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  9. Java静态代理和动态代理

    今天介绍一下代理设计模式,在业务场景中使用代理模式的好处有很多,包括什么权限校验,事务管理等等,具体有什么好处大家自动百度吧,我这里只解释代理模式的设计原理.首先这个设计模式出来的时候先是静态代理模式 ...

  10. java中的静态代理和动态代理,入门整理

    静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 ...

随机推荐

  1. Fiddler 4 断点调试(修改request请求参数)

    1.选中要测试的链接 2然后点击规则的Automatic Breakpoints 的Before Requests 3.重新发送请求找到测试的点链接 最终效果如下

  2. PyQt学习随笔:Model和View之间的数据互动过程

    在<PyQt学习随笔:Qt中tem Views(Model-Based)和Item Widgets(Item-Based)控件的用途和关系>中介绍了,Model用于存储数据,View用于展 ...

  3. PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的clicked信号参数QAbstractButton *解决办法

    一.引言 QDialogButtonBox本身只提供4种信号,分别是accepted.rejected.clicked和helpRequested,在<PyQt(Python+Qt)学习随笔:D ...

  4. 分别使用python和java练习冒泡排序

    冒泡排序算法的运作如下:(从小到大)   比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针 ...

  5. 中间件面试专题:kafka高频面试问题

  6. 初中的一些OI琐屑 & APIO2020 & NOI2020

    这篇文章会发布在我的博客上 https://www.cnblogs.com/dmoransky/(一个小习惯,把信息学竞赛的学习历程记录在个人博客中). 借这篇随笔回顾并简短总结一下我的初中OI(信息 ...

  7. 树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110940484长期持续带来更多项目与技术分享, ...

  8. 主从复制直接转换MGR_5.7验证试验

    环境信息 IP port role info 192.168.188.51 4000 node1 master 192.168.188.52 4000 node2 slave1 192.168.188 ...

  9. Tokyo 五年 IT 生活

    今天阳光甚好,在家中小屋,闲来无事,回顾一下这五年的历程.我想从来东京的缘由.东京的环境.生活.IT这四个方面介绍一下. 首先,说一下为什么我会来到东京. 电子信息专业毕业,大学实验室学习IT,毕业后 ...

  10. vue 修改数据

    通过数组中的方法改变数据 变异方法(改变原数组) push() pop() shift() unshift() splice() sort() reverse() 替换数组(生成新数组) filter ...