引言:

代理是基本的设计模式之一,它为你提供额外的或不同的操作而插入的用来代替实际对象的对象(委托对象)。这些对象通常涉及到与实际对象的通信,因此代理通常充当中间人的角色。--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. springmvc跨域问题

    1.跨域问题: 按照网上所有的方法试了一遍,都没跨过去,正在无助之际,使用filter按照下面的方法解决的时候出现了转机: 添加filter: package com.thc.bpm.filter; ...

  2. PyQt(Python+Qt)学习随笔:containers容器类部件QStackedWidget堆叠窗口属性

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.堆叠窗口简介 StackedWidget堆叠窗口部件为一系列窗口部件的堆叠,对应类为QStack ...

  3. PyQt学习随笔:QTableWidget项sizeHint的作用以及与QHeadView的sectionResizeMode、ResizeToContents的关系

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在学习QTableWidgetItem的sizeHint()方法时,Qt自带材料中介绍sizeHin ...

  4. 第二章、PyQt5应用构建详细过程介绍

    老猿Python博文目录 老猿Python博客地址 一.引言 在上节<第一章.PyQt的简介.安装与配置>介绍了PyQt5及其安装和配置过程,本节将编写一个简单的PyQt5应用,介绍基本的 ...

  5. PyQt(Python+Qt)学习随笔:Qt Designer中toolBar的toolButtonStyle属性

    tooButtonStyle属性保存主工具栏按钮的样式设置,用来表示工具栏按钮的文字和图标怎么显示. 该属性的可设置值类型为枚举类型Qt.ToolButtonStyle,它包含如下值: 该属性的缺省值 ...

  6. Shell命令和流程控制[linux常用命令的使用]

    在shell脚本中使用三类命令: unix命令 概念:管道.重定向.backtick 流程控制 1 unix命令 echo "some text":在屏幕上输出信息 ls:文件列表 ...

  7. MySQL Docker容器实例创建并进入MySQL命令行

    首先需要明白的一点是: docker镜像是一个模版,docker容器是一个实例,它可以被启动与关闭. 我们需要先有MySQL的docker镜像,使用命令: docker pull mysql 拉取最新 ...

  8. WordCount个人项目

    1.GitHub地址:https://github.com/lyh27/WordCount 2.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测 ...

  9. 题解-CTS2019 珍珠

    题面 CTS2019 珍珠 有 \(n\) 个在 \([1,d]\) 内的整数,求使可以拿出 \(2m\) 个整数凑成 \(m\) 个相等的整数对的方案数. 数据范围:\(0\le m\le 10^9 ...

  10. Acwing 120. 防线

    题目地址 题目简译:给定\(n\)个等差数列,每个等差数列的起点为\(s\),终点为\(e\),差为\(d\).整个序列中至多有一个位置所占数字是奇数.判断奇数位是否存在,如果不存在输出"T ...