从面相对象编程到面相切面编程,是一种代码组织方式的进化。

每一代的代码组织方式,其实是为了解决当时面对的问题。比如写编译器和写操作系统的时候的年代当然要pop,比如写界面的时候当然要oop,因为界面这东西是人造的约定俗成的,继承关系清晰明了,当写互联网软件的时候自然要面相服务sop。大型商务系统的编写,问题就更加复杂,aop就应运而生了。

AOP 应用:
1. 监控系统重要API的调用事件,用来监控系统的性能。
2.Authentication 权限
3. Caching 缓存
4. Context passing 内容传递
5. Error handling 错误处理
6. Lazy loading 懒加载
7. Debugging  调试
8. logging, tracing, profiling and monitoring 记录跟踪 优化 校准
9. Performance optimization 性能优化
10. Persistence  持久化
11. Resource pooling 资源池
12. Synchronization 同步
13. Transactions 事务

我们用最简单的性能监控来举个例子,记录一个服务所消耗的时间.

服务类,计算一个数的阶乘:

  1. public class FactorialUtil {
  2. public static int exFactirial(int n){
  3. PerformanceMonitor.begin("FactorialUtil -- exFactirial");
  4. int result = 1;
  5. for(int i=n;i>0;i--){
  6. result = result * i;
  7. }
  8. PerformanceMonitor.end();
  9. return result;
  10. }
  11. }

里面使用了PerformanceMonitor类,来计算时间,这个类特别的简单:

  1. public class PerformanceMonitor {
  2. private static ThreadLocal<Long> beginTime = new ThreadLocal<>();
  3.  
  4. public static void begin (String url){
  5. beginTime.set(System.currentTimeMillis());
  6. System.out.println("begin monitor "+url);
  7. }
  8.  
  9. public static void end (){
  10. long endTime = System.currentTimeMillis();
  11. System.out.println("end monitor");
  12. long costTime = endTime - beginTime.get();
  13. System.out.println("the method cost : " + costTime +"ms");
  14. }
  15. }

线程安全,记录begin的系统时间和在end的时候把消耗时间减出来。

这样写代码有个好处,代码清晰明了,问题是阶乘计算类需要插入性能监控相关的代码,如果性能监控的代码需要修改,修改起来也比较麻烦。如果什么功能也需要添加性能监控,加起来也是很蛋疼的事。这种代码枯燥无味,全是套路不说,还容易出错。

因此第一个版本的解决方案旋即提出,他使用的jdk提供的动态代理的功能。实现方式如下:

首先将功能实现分为接口层和实现层。以期将功能代码标准化,能面相接口编程

  1. public abstract class FactorialService {
  2. public abstract int exFactirial(int n);
  3. }
  1. public class FactorialServiceImpl extends FactorialService {
  2. @Override
  3. public int exFactirial(int n) {
  4. int result = 1;
  5. for(int i=n;i>0;i--){
  6. result = result * i;
  7. }
  8. return result;
  9. }
  10. }

第二步,将性能监控的代码,封装在jdk动态代理提供的handler类之中:

  1. public class PerformanceHandler implements InvocationHandler {
  2. private Object target;
  3. public PerformanceHandler(Object obj){
  4. this.target = obj;
  5. }
  6.  
  7. @Override
  8. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  9. PerformanceMonitor.begin("FactorialUtil -- exFactirial");
  10. Object result = method.invoke(target,args);
  11. PerformanceMonitor.end();
  12. return result;
  13. }
  14. }

第三步,调用服务,使用java的proxy类,将服务包裹起来。

  1. public static int invokeByproxy(int n){
  2. FactorialService target = new FactorialServiceImpl();
  3. PerformanceHandler handler = new PerformanceHandler(target);
  4. FactorialService proxy = (FactorialService) Proxy.newProxyInstance(
  5. target.getClass().getClassLoader(),
  6. target.getClass().getInterfaces(),
  7. handler);
  8. return proxy.exFactirial(8);
  9. }

这样写,也就是用了个代理模式。细节上倒是没什么瑕疵,问题只有一个成本太高,类太多。出错不容易,但是估计也没有多少人愿意这么写。接着新一代技术就出来了Cglib技术,本质差不多,先上写法:

  1. public class CglibProxy implements MethodInterceptor {
  2. private Enhancer enhancer= new Enhancer();
  3.  
  4. public Object getProxy(Class clazz){
  5. enhancer.setSuperclass(clazz);
  6. enhancer.setCallback(this);
  7. return enhancer.create();
  8. }
  9.  
  10. public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
  11. PerformanceMonitor.begin("FactorialUtil -- exFactirial");
  12. Object result = methodProxy.invokeSuper(o, args);
  13. PerformanceMonitor.end();
  14. return result;
  15. }
  16. }

代理类实现和上面的代理类实现差别不大,使用了Cglib jar包中的MethodInterceptor接口。类的内部使用的是Enhancer来实例化。

调用方式特别简单:

  1. public static int invokeByCglib(int n){
  2. CglibProxy proxy = new CglibProxy();
  3. FactorialServiceImpl service = (FactorialServiceImpl)proxy.getProxy(FactorialServiceImpl.class);
  4. return service.exFactirial(8);
  5. }

好处:减少了实现接口类,只要实现功能类和代理类就可以了。

问题:1.目标类里面的所有方法都被增加性能监控了。

  2.只能已方法作为单位增加性能监控的位置。

  3.每个新功能都要增加代理类,写起来很麻烦。

Spring AOP (Spring 3.x 企业应用开发实战读书笔记第六章)的更多相关文章

  1. Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)

    前言:工作之后一直在搞android,现在需要更多和后台的人员交涉,技术栈不一样,难免鸡同鸭讲,所以稍稍学习下. 这个例子取自于<Spring 3.x 企业应用开发实战>一书中的第二章,I ...

  2. 《精通Spring4.X企业应用开发实战》读后感第六章(容器事件)

  3. 《精通Spring4.X企业应用开发实战》读后感第六章(国际化)

  4. 《精通Spring4.X企业应用开发实战》读后感第六章(引用Bean的属性值)

  5. 《精通Spring4.X企业应用开发实战》读后感第六章(使用外部属性文件)

  6. 《精通Spring4.X企业应用开发实战》读后感第六章(属性编辑器)

  7. 《精通Spring4.X企业应用开发实战》读后感第六章(内部工作机制、BeanDefinition、InstantiationStrategy、BeanWrapper)

  8. iPhone与iPad开发实战读书笔记

    iPhone开发一些读书笔记 手机应用分类1.教育工具2.生活工具3.社交应用4.定位工具5.游戏6.报纸和杂志的阅读器7.移动办公应用8.财经工具9.手机购物应用10.风景区相关应用11.旅游相关的 ...

  9. 《精通Spring4.X企业应用开发实战》读后感第七章(AOP基础知识、jdk动态代理,CGLib动态代理)

随机推荐

  1. leetcode@ [30/76] Substring with Concatenation of All Words & Minimum Window Substring (Hashtable, Two Pointers)

    https://leetcode.com/problems/substring-with-concatenation-of-all-words/ You are given a string, s, ...

  2. C++ STL@ list 应用 (leetcode: Rotate Array)

    STL中的list就是一双向链表,可高效地进行插入删除元素. List 是 C++标准程式库 中的一个 类 ,可以简单视之为双向 连结串行 ,以线性列的方式管理物件集合.list 的特色是在集合的任何 ...

  3. dataStructure@ Check whether a given graph is Bipartite or not

    Check whether a given graph is Bipartite or not A Bipartite Graph is a graph whose vertices can be d ...

  4. hdoj 2045 不容易系列之(3)—— LELE的RPG难题

    不容易系列之(3)—— LELE的RPG难题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/O ...

  5. 你的iOS静态库该减肥了

    我有点震惊,国内的具有极少的有关静态库开发的内容,除了一些简单的如何教你开发,而且是原创还是copy,谁知道呢?细思极恐,不扯那么远了,这里就已切身的爬坑经历提供几个静态库瘦身的方案. 公司最近开发完 ...

  6. CSS边框与边界

    (上右下左依次体现)à边框的同一属性名称可以同时使用多个属性值 简化方案:border: 长度 形态 颜色 例如 border:1px solid black; 16.2 CSS中边界的使用 padd ...

  7. uml 在需求分析阶段的应用

    上一篇博客写了uml在软件开发过程中的应用,这以篇要详细介绍一下UML在需求分析过程中的应用. 以机房收费系统为例进行讲解,先介绍一个该系统. 首先该系统的用户分为三个等级,一般用户,操作员,管理员, ...

  8. PowerDesigner实用技巧小结(3)

    PowerDesigner实用技巧小结(3) PowerDesigner 技巧小结 sqlserver数据库databasevbscriptsqldomain 1.PowerDesigner 使用 M ...

  9. linux IO诊断命令集

    IO.sh ##iostat是查看磁盘活动统计情况 ##显示全部设备负载情况 r/s: 每秒完毕的读 I/O 设备次数.即 rio/s:w/s: 每秒完毕的写 I/O 设备次数.即 wio/s等 io ...

  10. Unity3d 网络编程(一)(Unity3d内建网络Network介绍)

    首先个人说说题外话,Unity3d使用的网络库核心是用C++实现的一款商业网络游戏引擎库. RakNet.所以对于移动设备来说,用Unity3d来写server是全然能够的,而且内建网络库的各项功能封 ...