文章目录

  • 导读
  • 问题
  • 概述
  • 改造
  • 其他相关接口/类

导读

Spring-AOP基础知识

Java-JDK动态代理

Java-CGLib动态代理


问题

另一篇博文中的问题

性能监视横切逻辑代码


概述

Java1.3以后,JAVA提供了动态代理技术,允许开发者在运行期创建接口的代理实例。

JDK的动态代理主要涉及java.lang.reflect包中的两个类:Proxy和InvocationHandler.

InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑并通过反射机制调用目标类的代码,动态的将横切逻辑和业务逻辑编织在一起。

而Proxy利用InvocationHandler动态的创建一个符合某一接口的实例,生成目标类的代理对象。


改造

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

首先我们移除性能监视的横切代码,如下

package com.xgj.aop.base.jdkproxy;/*** * * @ClassName: ForumServiceImpl* * @Description: ForumService实现类* * @author: Mr.Yang* * @date: 2017年8月12日 下午4:14:30*/
public class ForumServiceImpl implements ForumService {@Overridepublic void removeTopic(int topicId) {// 模拟业务逻辑System.out.println("模拟删除Topic,topicId=" + topicId);try {Thread.currentThread().sleep((long) (Math.random() * 1000 * 10));} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic void removeForum(int forumId) {// 模拟业务逻辑System.out.println("模拟删除forum,forumId=" + forumId);try {Thread.currentThread().sleep((long) (Math.random() * 1000 * 10));} catch (InterruptedException e) {e.printStackTrace();}}}

如上只编写了业务代码,移除的性能监视横切代码,放哪里呢?

InvocationHandler就是横切代码的家,编写实现类实现InvocationHandler 接口,重写invoke方法

比如:

package com.xgj.aop.base.jdkproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class PerformanceHandler implements InvocationHandler {private Object target;/*** * * @Title:PerformanceHandler* * @Description:构造函数, 入参target为业务目标类* * @param target*/public PerformanceHandler(Object target) {this.target = target;}// 性能监视的横切代码 + 业务代码@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// 开始监控 入参 方法的全限定名称PerformanceMonitor.begin(target.getClass().getName() + "."+ method.getName());// 通过反射调用业务类的目标方法Object object = method.invoke(target, args);// 结束监控PerformanceMonitor.end();return object;}
}

分析:

invoke方法中PerformanceMonitor相关的为性能监视的横切代码,我们发现,横切代码只出现一次,而不是像原来那样每个类中都有。

method.invoke()通过Java反射机制间接调用目标对象的方法,这样 InvocationHandler的invoke方法就将横切逻辑代码和业务类方法的业务逻辑代码编织到一起,所以可以将InvocationHandler看成一个编织器。

具体分析这段代码:

首先实现了InvocationHandler接口,重写invoke方法

public Object invoke(Object proxy, Method method, Object[] args)

其中

  • proxy是最终生成的代理实例,一般不会用到

  • method是被代理目标实例的某个具体方法,通过它可以发起目标实例方法的反射调用

  • args是被代理实例某个方法的入参,在方法反射调用时使用。

其次,在构造函数里通过target传入希望被代理的目标对象。 在invoke方法中,将目标对象传递给method.invoke()方法,并调用目标实例的方法。


测试类,利用Proxy创建ForumService接口的代理实例:

package com.xgj.aop.base.jdkproxy;import java.lang.reflect.Proxy;public class ForumServiceTest {public static void main(String[] args) {// 希望被代理的目标业务类ForumService target = new ForumServiceImpl();// 将目标类业务和横切代码编织到一起PerformanceHandler handler = new PerformanceHandler(target);// 根据编织了目标业务类逻辑和性能监控横切逻辑的InvocationHandler实例创建代理实例ForumService proxy = (ForumService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), handler);// 调用代理实例proxy.removeTopic(3);proxy.removeForum(1);}
}

上述代码完成了业务类代码和横切面代码的编织工作并生成了代理实例。

PerformanceHandler handler = new PerformanceHandler(target); —>将性能监视横切逻辑编织到ForumService实例中。

然后通过Proxy的 newProxyInstance()讲台方法为编织了业务逻辑和心梗监视横切逻辑的handler创建了一个符合ForumService接口的代理实例。

  • 第一个入参为类加载器

  • 第二个入参为创建代理实例所需要实现的一组接口

  • 第三个参数是整了业务逻辑和横切逻辑的编织器对象。

按照上述设置,这个代理实例就实现了目标业务类的所有接口,即ForumServiceImpl的ForumService接口。

这样就可以按照调用ForumService接口实例相同的方式调用代理实例了。

代理实例方法调用的时序图:

运行结果:


其他相关接口/类

ForumService.java

package com.xgj.aop.base.jdkproxy;/*** * * @ClassName: ForumService* * @Description: ForumService接口* * @author: Mr.Yang* * @date: 2017年8月12日 下午4:13:31*/
public interface ForumService {/*** * * @Title: removeTopic* * @Description: 根据topicId删除Topic* * @param topicId* * @return: void*/void removeTopic(int topicId);/*** * * @Title: removeForum* * @Description: 根据forumId删除Forum* * @param forumId* * @return: void*/void removeForum(int forumId);
}

PerformanceMonitor.java

package com.xgj.aop.base.jdkproxy;public class PerformanceMonitor {// 通过一个ThreadLocal保存与调用线程相关的性能监视信息private static ThreadLocal<MethoPerformance> performanceLocal = new ThreadLocal<MethoPerformance>();/*** * * @Title: begin* * @Description: 启动对某一目标方法的性能监视* * @param method* * @return: void*/public static void begin(String method) {System.out.println("begin to monitor:" + method);MethoPerformance methoPerformance = new MethoPerformance(method);performanceLocal.set(methoPerformance);}/*** * * @Title: end* * @Description: 输出性能监视结果* * @param method* * @return: void*/public static void end() {MethoPerformance methoPerformance = performanceLocal.get();// 打印出方法性能监视的结果信息methoPerformance.printPerformance();}
}

MethoPerformance.java

package com.xgj.aop.base.jdkproxy;public class MethoPerformance {private long beginTime;private long endTime;private String methodName;/*** * * @Title:MethoPerformance* * @Description:构造函数* * @param methodName*/public MethoPerformance(String methodName) {super();this.methodName = methodName;this.beginTime = System.currentTimeMillis();}/*** * * @Title: printPerformance* * @Description: 计算耗时* * * @return: void*/public void printPerformance() {endTime = System.currentTimeMillis();long cost = endTime - beginTime;System.out.println(methodName + " costs " + cost / 1000 + "秒\n");}
}

Java-JDK动态代理相关推荐

  1. Java - JDK动态代理原理

    Java - JDK动态代理原理 前言 一. JDK动态代理源码分析 1.1 生成目标代理类 getProxyClass0 1.1.1 KeyFactory 生成接口的虚引用 1.1.2 ProxyC ...

  2. java jdk动态代理学习记录

    转载自: https://www.jianshu.com/p/3616c70cb37b JDK自带的动态代理主要是指,实现了InvocationHandler接口的类,会继承一个invoke方法,通过 ...

  3. java jdk动态代理 cglib动态代理demo

    最近在研究java动态代理这块,以前也看了很多次java动态代理,感觉一直不是怎么明白,这两天看了看又明白了些,现给出我参考网上写的一个demo jdk动态代理实现: View Code import ...

  4. Java JDK 动态代理实现和代码分析

    JDK 动态代理 内容 一.动态代理解析 1. 代理模式 2. 为什么要使用动态代理 3. JDK 动态代理简单结构图 4. JDK 动态代理实现步骤 5. JDK 动态代理 API 5.1 java ...

  5. Java JDK 动态代理

    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代 ...

  6. 谁与争锋,JDK动态代理大战CGLib动态代理

    文章目录 一.前言 二.基本概念 三.JDK 和 CGLib动态代理区别 3.1 JDK动态代理具体实现原理 3.2 CGLib动态代理 3.3 两者对比 3.4 使用注意 四.JDK 和 CGLib ...

  7. Java基础-JDK动态代理

    JDK的动态代理依靠接口实现  代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. ...

  8. Java设计模式(五)代理设计模式—静态代理—JDK动态代理—Cglib动态代理

    文章目录 什么是代理模式 代理模式应用场景 代理的分类 静态代理 什么是静态代理 深入解析静态代理 小结 动态代理 什么是动态代理 JDK动态代理 原理和实现方式 代码实现 优缺点 Cglib动态代理 ...

  9. java代理(静态代理和jdk动态代理以及cglib代理)

    说到代理,脑袋中浮现一大堆代理相关的名词,代理模式,静态代理,jdk代理,cglib代理等等. 记忆特别深刻的是,一次面试中,一位面试官问我,spring的AOP核心采用的设计模式是什么什么模式,阅读 ...

  10. 【java】JDK动态代理原理

    文章目录 1. 示例 2. 原理 3. 为什么必须要基于接口? 1. 示例 首先,定义一个接口: public interface Staff {void work(); } 然后,新增一个类并实现上 ...

最新文章

  1. Centos6.3下利用open***部署远程×××服务
  2. class函数 python_python函数之classmethod()
  3. C++中的const
  4. Python单元测试框架Pyunit 的使用
  5. CVPR 2020 | 反传统的无监督人脸旋转方案:旋转-渲染
  6. 让360安全浏览器默认使用谷歌内核
  7. 【英语学习】【Level 08】U02 Movie Time L4 From the page to the big screen
  8. setsockopt设置套接口选项
  9. Ubuntu日志的一些笔记
  10. Swift的一些问题
  11. Zookeeper C API 指南二(监视(Wathes), 基本常量和结构体介绍)
  12. 大数据技术原理与应用----大数据概述
  13. 数据结构零基础入门(初学者也能看懂):队列使用场景之无锁技术
  14. Gauss 求积公式及代码
  15. 德保罗大学计算机专业,2020年德保罗大学排名TFE Times美国最佳计算机科学硕士专业排名第75...
  16. 网站备案各个管局的审核时间多久?
  17. Unity 3D涂色
  18. PCAT 点云标注软件
  19. VS2017专业版和企业版下载激活
  20. 全球人造丝卫生棉条行业调研及趋势分析报告

热门文章

  1. kotlin 反射java类_关于Kotlin反射中实例化类的问题
  2. java src 文件路径_java中获得src路径下文件的常用方法
  3. 借助联合体union的特性实现检测当前计算机环境采用的是大端模式还是小端模式
  4. pyspark rdd 基本操作
  5. wireshark网络分析就这么简单 pdf_才知道,PDF、Excel、Word互转这么简单?涨知识了...
  6. python线性回归实例_sklearn+python:线性回归案例
  7. 机器学习笔记:误差的来源(bias variance)
  8. 听说你想去大厂看妹子,带你看看腾讯产品运营岗超详细面经
  9. Python入门100题 | 第005题
  10. Python编程基础:第三十三节 文件复制Copy a File