引言:

代理是基本的设计模式之一,它为你提供额外的或不同的操作而插入的用来代替实际对象的对象(委托对象)。这些对象通常涉及到与实际对象的通信,因此代理通常充当中间人的角色。--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. 20191012_WMI中可以看到有打印机, 设备管理器中没有

    开发过程中使用SELECT * FROM Win32_Printer 查看设备有一个备份打印机, 并且被设置为默认打印机了, 但是设备管理器中没有 解决方法: 使用系统自带的测试WMI  (Windo ...

  2. OpenCV-Python setMouseCallback回调函数中图像变量img的传递方法解析

    ☞ ░ 前往老猿Python博文目录 ░ 一.使用全局变量进行变量传递 OpenCV-Python中可以使用setMouseCallback来设置鼠标事件的回调函数,我们来看个样例. 1.1.案例1代 ...

  3. PyQt(Python+Qt)学习随笔:Qt Designer中spacer部件的orientation属性

    在Designer的spacers部件中有2个部件,分别是Horizontal Spacer和Vertical Spacer,这两个部件都有orientation属性,表示Spacer部件的方向. 如 ...

  4. VMware-workstation-full-10.0.4安装

    1.下载安装包 链接:https://pan.baidu.com/s/1SBd3KP4Nxk-RaHLv7HIYTw 提取码:8zkm 2.安装VMware-workstation 双击安装包 选择典 ...

  5. 深入浅出让你理解什么是LLVM

    什么是LLVM 转载自https://www.jianshu.com/p/1367dad95445 LLVM项目是模块化.可重用的编译器以及工具链技术的集合. 美国计算机协会 (ACM) 将其2012 ...

  6. Springboot集成xxl-Job

    一.前言 xxl-job一个轻量级的分布的调度中间件,详情介绍自己到官网看:https://www.xuxueli.com/xxl-job/ 二.客户端(执行器) 引入依赖compile group: ...

  7. Typora入门教程

    Typora学习教程 1目录 [TOC]加空格 ,自动生成 目录 1目录 2图片 3下划线 4删除线 5解决语法和内容冲突 6加粗 6.1测试页面跳转 7倾斜 8超链接 9模块 10引用 11表格 1 ...

  8. JavaScript异步编程的四种方法

    1.回调函数 f1(f2); 回调函数是异步编程的基本方法.其优点是易编写.易理解和易部署:缺点是不利于代码的阅读和维护,各个部分之间高度耦合 (Coupling),流程比较混乱,而且每个任务只能指定 ...

  9. (8)ASP.NET Core3.1 Ocelot Consul服务注册与发现

    1.服务注册与发现(Service Discovery) ●服务注册:我们通过在每个服务实例写入注册代码,实例在启动的时候会先去注册中心(例如Consul.ZooKeeper.etcd.Eureka) ...

  10. STL—— 容器(vector)的内存分配,声明时的普通构造&带参构造

    vector 的几种带参构造 & 初始化与内存分配: 1. 普通的带参构造: vector 的相关对象可以在声明时通过 vector 的带参构造函数进行内存分配,如下: 1 #include ...