1. 动态代理


  • 动态代理就是通过代理类是代理类与相关接口不直接发生联系,而在运行期(Runtime)实现动态关联。
  • 动态代理主要用到java.lang.reflect包中的两个类,InvocationHandler接口和Proxy类。
  • 动态代理相较于静态代理最大的不同就是:动态代理的代理类不需要手动生成,该代理类是在运行期间动态生成的,这个动态生成的代理类已经实现代理对象的相关接口(Interface)。在生成代理类的同时,必须提供一个handler,这个handler有InvocationHandler提供,同时用来接管实际的工作。

2. InvocationHandler接口


(1)接口声明:
public interface InvocationHandler
  • 每一个动态代理类都必须实现InvocationHandler接口,InvocationHandler是代理实例(代理的真实对象),的调用处理程序实现的接口,当通过代理实例调用一个方法的时候,该方法的调用就会指派到它调用处理程序(InvocationHandler接口)的 invoke 方法。
(2)invoke方法声明:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
参数意义:Object proxy: 指代所代理的真实对象,也就是真实对象的代理
Method method: 指代所调用的真实对象的某个方法的Method对象
Object[] args: 指代所代理的真实对象某个方法的参数

3. Proxy类


(1)类声明:
public class Proxy extends Object implements Serializable
  • Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类(JDK).
  • Proxy类根据已经提供的相关接口和被代理的类就可以利用反射机制得到实现的方法,根据Proxy类的newProxyInstance(...)方法生成代理类。
(2)newProxyInstance方法声明:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
参数意义:
ClassLoader loader: 类加载器,就是把动态生成的代理类的字节码文件加载到JVM虚拟机中,一般使用被代理类的类加载器
Class<?>[] interfaces:为代理对象提供的接口,就是被代理类实现的接口
InvocationHandler h: 当代理对象调用方法的时候关联到InvocationHandler对象上,也就是前面说的*调用处理程序*(有待更深理解)

4.动态代理模式实现


package com.manu;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TestTrendsProxy {
public static void main(String[] args) {
Subject man = new Man();
Proxy p = new Proxy(man);
//通过java.lang.reflect.newProxyInstance(...)方法获得真实对象的代理对象
Subject subject = (Subject)java.lang.reflect.Proxy.newProxyInstance(man.getClass().getClassLoader(), man.getClass().getInterfaces(), p);
//通过代理对象调用真实对象相关接口中实现的方法,这个时候就会跳转到这个代理对象所关联的handler的invoke()方法去执行
subject.shopping();
//获得真实对象的代理对象所对应的Class对象的名称,用字符串表示
System.out.println(subject.getClass().getName());
//调用处理程序的表示
InvocationHandler handler = java.lang.reflect.Proxy.getInvocationHandler(subject);
System.out.println(handler);
}
}
//被代理人和代理人要执行的动作
interface Subject{
void shopping();
}
//被代理类
class Man implements Subject{
private String name="Tom";
public void shopping() {
System.out.println(name+"要去买东西...");
}
}
//代理类
class Proxy implements InvocationHandler{
private Object target;//要代理的真实对象
public Proxy(Subject target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy:"+proxy.getClass().getName());
System.out.println("购买之前的评估工作...");
method.invoke(target, args);
System.out.println("购买之后的满意度调查...");
return null;
}
}

下面是运行结果:

运行结果:
proxy:com.manu.$Proxy0
购买之前的评估工作...
Tom要去买东西...
购买之后的满意度调查...
com.manu.$Proxy0
com.manu.Proxy@6bc7c054

运行结果中出现的$Proxy0是subject.getClass().getName())得到的,返回的是类的名称,这是在运行时动态创建的,命名方式貌似是$Proxy+编号构成。整个代理过程主要体现在一个handler上。

如果选择关注微信公众号:jzman-blog,一起交流学习!


关于java动态代理模式的更多相关文章

  1. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

  2. java动态代理模式

    java动态代理机制详解 Spring的核心AOP的原理就是java的动态代理机制. 在java的动态代理机制中,有两个重要的类或接口: 1.InvocationHandler(Interface): ...

  3. Java动态代理模式浅析

    Java代理设计模式 - 静态代理 Java中的动态代理 - 调用处理器 代理设计模式的UML图: 我将首先介绍Java中的各种代理实现方法 Java代理设计模式 - 静态代理 这个例子非常简单,只有 ...

  4. java 动态代理模式(jdk和cglib)

    package proxy.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Met ...

  5. Java 动态代理模式浅析

    目录 Java代理设计模式 - 静态代理 静态代理的优点 静态代理的缺点 Java中的动态代理 - 调用处理器 主要笔记: 动态代理类的限制 代理设计模式的UML图: 我将首先介绍Java中的各种代理 ...

  6. JAVA代理模式与动态代理模式

    1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某 ...

  7. Java设计模式系列之动态代理模式(转载)

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...

  8. Java静态代理与动态代理模式的实现

    前言:    在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总找不到时间去找他,他也没办法.后来,房东想了一个办法,他找到 ...

  9. java jdk动态代理模式举例浅析

    代理模式概述 代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色. java中常用的动态代理模式为jdk动态代理和c ...

随机推荐

  1. 本地Hadoop集群搭建

    什么是Hadoop? Hadoop是一个开源的Apache项目,通常用来进行大数据处理. Hadoop集群的架构: master节点维护分布式文件系统的所有信息,并负责调度资源分配,在Hadoop集群 ...

  2. scrapy mid中间件一般处理方法

    import user_agent import requests class UA_midd(object): def process_request(self,request,spider): r ...

  3. 解决 unable to lock the administration directory (/var/lib/dpkg/) 问题

    阿里开源镜像站提供了raspbian的软件包镜像,国内的用户可以选择改用阿里镜像站作为更新源. 但是在更换源之后,执行 sudo apt-get update && apt-get u ...

  4. python第一次作业

    import turtle turtle.pensize(2) turtle.pencolor("black") turtle.fillcolor("red") ...

  5. 移动端Rem适配(基于vue-cli3 ,ui框架用的是vant-ui)

    介绍postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 remlib-flexible 用于设置 rem 基准值 1.安装lib-flexible(用于设置 rem 基准值 ...

  6. MySQL设置外键报错 #1452 - Cannot add or update a child row: a foreign key constraint fails 解决方法

    MySQL数据库,当我尝试在A表中设置B表的主键为外键时,报出错误:#1452 - Cannot add or update a child row: a foreign key constraint ...

  7. 【Weiss】【第03章】练习3.13:桶排序

    [练习3.13] 利用社会安全号码对学生记录构成的数组排序.编写一个程序进行这件工作,使用具有1000个桶的基数排序并且分三趟进行. Answer: 首先,对社会安全号码不了解的就把它当成一个不超过9 ...

  8. sqlmap详解

    sqlmap是一个自动化的sql注入工具,其主要功能是扫描.发现并利用给定URL的SQL注入漏洞,内置了很多绕过插件,支持的数据库有MySQL, Oracle,PostgreSQL, Microsof ...

  9. BeanShell调用自己写的jar包进行MD5加密

    1.在eclipse中新建一个java工程,工程名随意. 2.在工程中添加一个package,package名为md5,在package下添加一个class,class名为mymd5. package ...

  10. Python文本文件读写操作时的字符编码问题

    说明:文本文件的字符编码问题只存在t模式中,如:open('a.txt', mode='rt') 编码(encode): 我们输入的任何字符想要以文件(如.txt)的形式保存在计算机的硬盘上, 必须先 ...