AOP 详解
1. 需求:统计方法执行的性能情况(来源:《精通Spring 4.x》)
// 性能监视类 PerformanceMonitor
package com.noodles.proxy;
public class PerformanceMonitor{
// 通过一个ThreadLocal, 保存与调用线程相关的性能监视信息
private static ThreadLocal<MethodPerformance> performanceRecord =
new ThreadLocal<MethodPerformance>();
// 开始对某一方法进行性能监视
public static void begin(String method){
System.out.println("性能监视开始...");
MethodPerformance mp = new MethodPerformance(method);
performanceRecord.set(mp);
}
// 对某一方法的性能监视结束
public static void end(){
System.out.println("性能监视结束...");
MethodPerformance mp = performanceRecord.get();
// 打印性能监视结果信息
mp.printPerformance();
}
}
// 记录性能监视类 MethodPerformance
public class MethodPerformance {
private long begin;
private long end;
private String serviceMethod;
// 构造函数
public MethodPerformance(String serviceMethod){
this.serviceMethod = serviceMethod;
// 程序执行的开始时间
this.begin = System.currentTimeMillis();
}
// 打印方法执行消耗的时间
public void printPerformance(){
end = System.currentTimeMillis();
long elapse = end - begin;
System.out.println(serviceMethod + " 花费 " + elapse + "毫秒");
}
}
// 业务类中完成性能监视的功能
public class ForumServiceImpl implements ForumService {
// 方法一: removeTopic
public void removeTopic(int topicId){
// 开始性能监视
PerformanceMonitor.begin(
"com.noodles.proxy.ForumServiceImpl.removeTopic");
System.out.println("模式删除Topic:" + topicId);
try{
Thread.currentThread().sleep(20);
}catch(Exception ex){
throw new RuntimeException(e);
}
// 结束性能监视
PerformanceMonitor.end();
}
// 方法二: 根据id,更新个人信息
public void updateInfoById(int userId){
// 开始性能监视
PerformanceMonitor.begin("com.noodles.proxy.ForumServiceImpl.updateInfoById");
System.out.println("模拟更新个人信息:" + userId);
try{
Thread.currentThead().sleep(40);
}catch(Exception ex){
throw new RuntimeException(ex);
}
// 结束性能监视
PerformanceMonitor.end();
}
}
1.2 上述代码存在问题
ForumServiceImpl中每个方法都存在性能监视的代码,存在冗余;- 性能监视与
ForumServiceImpl业务不相关,属于系统功能,此处,存在耦合; - AOP(Aspect Oriented Programming, 面向切面编程)也就是为解决此类问题,采用横向抽取的机制,将大量重复,且与业务不相关的代码(如性能监控,事务管理以及日志记录等)剥离,作为一个切面类;
2. AOP 详解
- AOP 的核心为切面,切面 = 切点 + 增强;
- 增强(Advice): 从业务类中剥离处理的非业务代码(如上例中的性能监控代码);
- 切点(Pointcut): 用于解决在业务类中的哪个位置来执行增强(Advice);

2.1 AOP 底层技术
- AOP 底层依赖的是动态代理技术;根据所代理的类有无实现接口,分为:
- JDK 动态代理:Proxy类和InvocationHandler类
- CGLib 动态代理:
/**
*JDK 动态代理
*/
// 实现InvocationHandler接口
public class PerformanceHandler implements InvocationHandler{
private Object target; // target 为业务类
public PerformanceHandler(Object target){
this.target = target;
}
// 实现 invoke()方法, 返回代理对象
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 开启性能监视
PerformanceMonitor.begin(
target.getClass().getName() + "." + method.getName());
// 通过反射调用业务方法
Object obj = method.invoke(target, args);
// 结束性能监视
PerformanceMonitor.end();
return obj;
}
}
// 编写测试类 ForumServiceTest
public class ForumServiceTest {
// 希望被代理的目标业务类
ForumService target = new ForumServiceImpl();
// 将目标业务类和横切代码编织到一起
PerformanceHandler handler = new PerformanceHandler(target);
// 创建代理类
ForumService proxy = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler);
// 调用代理实例
proxy.removeTopic(1011);
proxy.updateInfoById(567);
}
/**
* CGLib 代理
* 采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势织入
* 横切逻辑;
*/
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
enhancer.setSuperClass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
// 拦截父类所有方法的调用
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
PerformanceMonitor.begin(obj.getClass().getName() + "." + method.getName());
Object result = proxy.invokeSuper(obj, args);
PerformanceMonitor.end();
return result;
}
}
// 编写测试方法 ForumServiceTest
public class ForumServiceTest {
@Test
public void proxy(){
CglibProxy proxy = new CglibProxy();
ForumServiceImpl forumService =
(ForumServiceImpl)proxy.getProxy(ForumServiceImpl.class);
forumService.removeTopic(1011);
forumService.updateInfoById(567);
}
}
参考资料:
AOP 详解的更多相关文章
- Spring4 AOP详解
Spring4 AOP详解 第一章Spring 快速入门并没有对Spring4 的 AOP 做太多的描述,是因为AOP切面编程概念不好理解.所以这章主要从三个方面详解AOP:AOP简介(了解),基于注 ...
- 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理
Spring AOP详解 . JDK动态代理.CGLib动态代理 原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...
- [Spring学习笔记 5 ] Spring AOP 详解1
知识点回顾:一.IOC容器---DI依赖注入:setter注入(属性注入)/构造子注入/字段注入(注解 )/接口注入 out Spring IOC容器的使用: A.完全使用XML文件来配置容器所要管理 ...
- Spring AOP详解(转载)所需要的包
上一篇文章中,<Spring Aop详解(转载)>里的代码都可以运行,只是包比较多,中间缺少了几个相应的包,根据报错,几经百度搜索,终于补全了所有包. 截图如下: 在主测试类里面,有人怀疑 ...
- Spring AOP详解及简单应用
Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...
- 转:Spring AOP详解
转:Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...
- Spring全家桶——SpringBoot之AOP详解
Spring全家桶--SpringBoot之AOP详解 面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方 ...
- Spring Aop 详解二
这是Spring Aop的第二篇,案例代码很详解,可以查看https://gitee.com/haimama/java-study/tree/master/spring-aop-demo. 阅读前,建 ...
- AOP详解之三-创建AOP代理后记,创建AOP代理
AOP详解之三-创建AOP代理后记,创建AOP代理. 上篇文章已经获取到了AOP的信息,接下来就是拿着这些AOP的信息去创建代理了. 首先我们看下创建AOP代理的入口处. //这个方法将返回代理类 p ...
随机推荐
- Selenium 管理 Cookies
使用 Selenium ,还可以方便地对 Cookies 进行操作,例如获取.添加 .删除 Cookies 等 from selenium import webdriver browser = web ...
- 系统日志:/var/log/messages
/var/log/messages 存放的是系统的日志信息,它记录了各种事件,基本上什么应用都能往里写日志,在做故障诊断时可以首先查看该文件内容 [root@mirh5_center1_111.231 ...
- es 5.0 拼音分词器 mac
安装方法和ik中文分词器一样, 先下载: https://github.com/medcl/elasticsearch-analysis-pinyin 执行: mvn package; 打包成功以后, ...
- MPAndroidChart market右边显示不全问题
//lineChart.setMarkerView(new CustomChartMarkerView(activity, R.layout.line_chart_maker));//add mark ...
- 122、详解Glide图片加载库常用方法
转载:http://blog.csdn.net/android_xiong_st/article/details/53129256 Glide加载网络图片, 显示的还是以前的图片! (最全解决方案!) ...
- (转载)Recyclerview | Intent与Bundle在传值上的区别 | 设置布局背景为白色的三种方法
用Recyclerview实现列表分组.下拉刷新以及上拉加载更多 http://www.jianshu.com/p/be62ce21ea57 Intent与Bundle在传值上的区别http://b ...
- pycharm2016.2.3注册码到期, 激活, 破解版
python工具下载: https://pan.baidu.com/s/1kVEDOrl#list/path=%2F 密码:ko1i 注册码有效期是一年,到期后需再次激活 分享破解版 或者重新注册码激 ...
- 大智慧F10离线资料压缩包带F10关键字过滤软件--更新于2014-01-06.rar 184MB
大智慧F10离线资料包带F10关键字过滤软件--更新于2014-01-06.rar 移步到百度网盘下载: http://pan.baidu.com/s/1c01PDnE
- linux 简单搭建git服务器
如果使用git的人数较少,可以使用下面的步骤快速部署一个git服务器环境. 1. 生成 SSH 公钥 每个需要使用git服务器的工程师,自己需要生成一个ssh公钥进入自己的~/.ssh目录,看有没有用 ...
- MySQL外键和高级查询(连接查询、联合查询、子查询、去重查询)
MySQL的外键 什么是外键,很简单保持数据一致性的一个约束键.如果你有两张表,第一张是学生表,第二张表是一个成绩表,我们来看看保持数据一致性,其实在Django等框架的模型中中也能做关联获取对象. ...