众所周知,Java是面向对象语言的有力代表,提到java我们就会立即想到面向对象,提到面向对象我们就会想到java。然而面向对象也并非完美无缺的,它更注重于对象层次结构方面的东西,对于如何更好的管理对象行为内部结构,还存在着些许不足。那么我们如何使这个问题的得到更完美的解决呢?答案就是AOP。

AOP:Aspect-Oriented Programming。AOP是OOP的补充,是GOF的延续。我们知道设计模式是对于面向对象设计中经验的总结,它孜孜不断追求的就是调用者与被调用者之间的解耦。有了设计模式我们可以更有效的利用面向对象的特性,使得整个软件设计更加灵活、优雅。但是设计模式是基于面向对象的思想而形成的,更多的时候关注的是对象层次的东西,在解决对象行为内部问题方面却有些不足。AOP的出现恰恰就是对面向对象思想做出了完美的补充。

说到AOP,我们就不得不来提一下软件的纵向和横向问题。从纵向结构来看就是我们软件系统的各个模块,它主要负责处理我们的核心业务(例如商品订购、购物车查看);而从横向结构来看,我们几乎每个系统又包含一些公共模块(例如权限、日志模块等)。这些公共模块分布于我们各个核心业务之中(例如订购和查看商品明细的过程都需要检查用户权限、记录系统日志等)。这样一来不仅在开发过程中要处处关注公共模块的处理而且开发后维护起来也是十分麻烦。而有了AOP之后将应用程序中的商业逻辑同对其提供支持的通用服务进行分离,使得开发人员可以更多的关注核心业务开发。

下面我们就以一个简单的例子来看一下AOP吧!比如说,我们现在要开发的一个应用里面有很多的业务方法,但是,我们现在要对这个方法的执行做全面监控,或部分监控.也许我们就会在要一些方法前去加上一条日志记录,我们写个例子看看我们最简单的解决方案
我们先写一个接口IHello.java代码如下:

[java] view plaincopy print?
  1. public interface IHello{
  2. /** *//**
  3. * 假设这是一个业务方法
  4. *@param name
  5. */
  6. void sayHello(String name);
  7. }

里面有个方法,用于输入"Hello" 加传进来的姓名;我们去写个类实现IHello接口

[java] view plaincopy print?
  1. public class Helloimplements IHello{
  2. public void sayHello(String name){
  3. System.out.println("Hello" + name);
  4. }
  5. }

现在我们要为这个业务方法加上日志记录的业务 , 我们在不改变原代码的情况下 , 我们会去怎么做呢 ? 也许 , 你会去写一个类去实现 IHello 接口 , 并依赖 Hello 这个类 . 代码如下 :

[java] view plaincopy print?
  1. public class HelloProxyimplements IHello{
  2. private IHello hello;
  3. public HelloProxy(IHello hello){
  4. this.hello= hello;
  5. }
  6. public void sayHello(String name){
  7. Logger.logging(Level.DEBUGE,"sayHello method start.");
  8. hello.sayHello(name);
  9. Logger.logging(Level.INFO,"sayHello method end!");
  10. }
  11. }

从上面的代码我们可以看出,hello对象是被HelloProxy这个所谓的代理态所创建的.这样,如果我们以后要把日志记录的功能去掉.那我们只要把得到hello对象的的具体实现改为Hello的就可以。上面的代码 就是对AOP的最简单的视线,但是我们接下来想,如果我们要在很多业务逻辑之前加日志的话,那么,我们是不是要去写很多个HelloProxy这样的类呢.没错,是的.其实也是一种很麻烦的事.在jdk1.3以后.jdk跟我们提供了一个API java.lang.reflect.InvocationHandler的类. 这个类可以让我们在JVM调用某个类的方法时动态的为些方法做些什么事.让我们把以上的代码改一下来看看效果.

同样,我们写一个IHello的接口和一个Hello的实现类.在接口中.我们定义两个方法;代码如下 :

IHello.java

[java] view plaincopy print?
  1. package sinosoft.dj.aop.proxyaop;
  2. public interface IHello{
  3. /** *//**
  4. * 业务处理A方法
  5. *@param name
  6. */
  7. void sayHello(String name);
  8. /** *//**
  9. * 业务处理B方法
  10. *@param name
  11. */
  12. void sayGoogBye(String name);
  13. }

Hello.java

[java] view plaincopy print?
  1. package sinosoft.dj.aop.proxyaop;
  2. public class Helloimplements IHello{
  3. public void sayHello(String name){
  4. System.out.println("Hello" + name);
  5. }
  6. public void sayGoogBye(String name){
  7. System.out.println(name+" GoodBye!");
  8. }
  9. }

我们一样的去写一个代理类.只不过.让这个类去实现java.lang.reflect.InvocationHandler接口,代码如下:

[java] view plaincopy print?
  1. package sinosoft.dj.aop.proxyaop;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. import java.lang.reflect.Proxy;
  5. public class DynaProxyHelloimplements InvocationHandler{
  6. /** *//**
  7. * 要处理的对象(也就是我们要在方法的前后加上业务逻辑的对象,如例子中的Hello)
  8. */
  9. private Object delegate;
  10. /** *//**
  11. * 动态生成方法被处理过后的对象 (写法固定)
  12. *
  13. *@param delegate
  14. *@param proxy
  15. *@return
  16. */
  17. public Object bind(Object delegate){
  18. this.delegate= delegate;
  19. return Proxy.newProxyInstance(
  20. this.delegate.getClass().getClassLoader(),this.delegate
  21. .getClass().getInterfaces(),this);
  22. }
  23. /** *//**
  24. * 要处理的对象中的每个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法只能通过此方法调用
  25. * 此方法是动态的,不是手动调用的
  26. */
  27. public Object invoke(Object proxy, Method method, Object[] args)
  28. throws Throwable{
  29. Object result= null;
  30. try {
  31. //执行原来的方法之前记录日志
  32. Logger.logging(Level.DEBUGE, method.getName()+ " Method end .");
  33. //JVM通过这条语句执行原来的方法(反射机制)
  34. result= method.invoke(this.delegate, args);
  35. //执行原来的方法之后记录日志
  36. Logger.logging(Level.INFO, method.getName()+ " Method Start!");
  37. } catch (Exception e){
  38. e.printStackTrace();
  39. }
  40. //返回方法返回值给调用者
  41. return result;
  42. } }

从上面的例子我们看出.只要你是采用面向接口编程,那么,你的任何对象的方法执行之前要加上记录日志的操作都是可以的.他(DynaPoxyHello)自动去代理执行被代理对象(Hello)中的每一个方法,一个java.lang.reflect.InvocationHandler接口就把我们的代理对象和被代理对象解藕了

from: http://blog.csdn.net/csh624366188/article/details/7650150

Java程序员从笨鸟到菜鸟之(七十三)细谈Spring(五)spring之AOP底层大揭秘相关推荐

  1. Java程序员从笨鸟到菜鸟之(十三)java网络通信编程

    首先声明一下,刚开始学习Java网络通信编程就对他有一种畏惧感,因为自己对网络一窍不通,所以...呵呵..你懂得,昨天又仔细的学习了一遍,感觉其实java网络编程也没想象的那么难,不信,咱一起看看.. ...

  2. Java程序员从笨鸟到菜鸟全部博客目录

    本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.NET/csh624366188 欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章 大 ...

  3. Java程序员从笨鸟到菜鸟之(序言)+全部链接

    http://blog.csdn.net/csh624366188 大学上了一年半,接触java也一年半了,虽然中间也有其他东西的学习,但是还是以java为主路线,想想这一年半,除去前半年几乎全玩了, ...

  4. Java程序员由笨鸟到菜鸟 电子版书正式发布 欢迎大家下载

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 欢迎关注 ...

  5. Java程序员从笨鸟到菜鸟之(五)java开发常用类(包装,数字处理集合等)(下)...

     本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 写在前面:由于前天项目老师建设局的项目快到验收阶段,所以,前天晚上通宵,昨天睡了大半天, ...

  6. Java程序员从笨鸟到菜鸟之(一百零九)一步一步学习webservice(三)开发第一个基于XFire的webservice

    在日常开发中,常用的webservice引擎主要有Axis,axis2,Xfire以及cxf(Xfire的升级版).现在只有axis2和cxf官方有更新.今天我们先以一个比较老的引擎为例.来讲诉一下w ...

  7. Java程序员从笨鸟到菜鸟之(一百零八)一步一步学习webservice(二)webservice基本原理

    本来这第二篇打算讲解"开发第一个基于XFire的webservice"的内容来着.但是想想.开发实例只是局限于了会用的层面上.如果想真正的理解webservice还是需要挖掘其原理 ...

  8. Java程序员从笨鸟到菜鸟之(五)java开发常用类(包装,数字处理集合等)(下)

    写在前面:由于前天项目老师建设局的项目快到验收阶段,所以,前天晚上通宵,昨天睡了大半天,下午我们宿舍聚会,所以时间有点耽误,希望大家见谅 上接: Java程序员从笨鸟到菜鸟之(四)java开发常用类( ...

  9. Java程序员从笨鸟到菜鸟之(一百零六)java操作office和pdf文件(四)页面列表导出cvs,excel、pdf报表.

    在平常的开发中我们常常遇到不仅仅只是导出excel报表的情况.有时候也需要导出pdf或者CSV报表.其实原理都差不多.刚开始本来不打算也这篇博客介绍这个的.感觉这篇博客和前面的博客有点雷同.原理基本都 ...

  10. Java程序员从笨鸟到菜鸟之(一百零四)java操作office和pdf文件(二)利用POI实现数据导出excel报表...

    在上一篇博客中,我们简单介绍了java读取word,excel和pdf文档内容 ,但在实际开发中,我们用到最多的是把数据库中数据导出excel报表形式.不仅仅简单的读取office中的数据.尤其是在生 ...

最新文章

  1. 基于单幅图像一致性学习的弱光视频增强(CVPR2021)
  2. ArcGIS Server 10.1动态图层 以及Windows Phone/Silverlight客户端实现
  3. sklearn模型评估
  4. win10操作技巧介绍,很实用!
  5. 港中文开源基于PyTorch的多任务人脸识别框架
  6. openstreetmap_OpenStreetMap成立10周年,开源医疗设备等等
  7. list 相加_Python 基础 list类、运算符
  8. python是什么 自学-初学 Python 者自学 Anaconda 的正确姿势是什么?
  9. access计算机二级改工号,Access新手来看:如何更改表/窗体/报表...得名字
  10. 数据清洗Chap5——数据转换
  11. 程序员必须掌握的十大经典算法
  12. 2018秋招360测评试题及其答案
  13. HTML5实时显示摄像头视频
  14. Android TabLayout设置选中状态标题字体大小,粗细
  15. 如何给视频添加水印logo?
  16. 4g网络设置dns地址_网速变慢?你可能需要先设置好 DNS | 科普
  17. 带你用selenium IDE的录制第一个自动化测试脚本
  18. 功能测试和自动化测试的优缺点
  19. 年底搞个基于C语言的运动会学生志愿者管理系统
  20. 双柱式机械式举升机设计(论文+DWG图纸)

热门文章

  1. android intent-fliter 标准Category
  2. 速神经网络的训练算法LARS/LAMB工作原理 --UC Berkeley在读博士生尤洋
  3. kaggle比赛模型融合指南
  4. 深度 | 宽客玩转华尔街:谁才是新的“华尔街之王”?
  5. 同时存多个变量缓存 微信小程序_微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解...
  6. MySQL-体系结构以及常用存储引擎MyISAM和InnoDB初探
  7. 高并发-【抢红包案例】之二:使用悲观锁方式修复红包超发的bug
  8. MyBatis-05 MyBatis XML方式之update/delete元素
  9. 分布式消息技术 Kafka
  10. SP Session