集装箱学习(两):动手模拟AOP
简单的说,Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架。
上文已经介绍模拟IoC实现,这篇文章来动手模拟AOP。
AOP简述
面向对象强调"一切皆是对象",是对真实世界的模拟。然而面向对象也并不是完美无缺的,它更注重于对象层次结构方面的东西。对于怎样更好的管理对象行为内部结构,还存在着些许不足。那么我们怎样使这个问题的得到更完美的解决呢?答案就是AOP。
AOP:Aspect-Oriented Programming。AOP是OOP的补充。是GOF的延续。
我们知道设计模式是对于面向对象设计中经验的总结。它孜孜不断追求的就是调用者与被调用者之间的解耦。
有了设计模式我们能够更有效的利用面向对象的特性,使得整个软件设计更加灵活、优雅。可是设计模式是基于面向对象的思想而形成的。很多其它的时候关注的是对象层次的东西,在解决对象行为内部问题方面却有些不足。
AOP的出现恰恰就是对面向对象思想做出了完美的补充。
说到AOP,我们就不得不来提一下软件的纵向和横向问题。从纵向结构来看就是我们软件系统的各个模块。它主要负责处理我们的核心业务(比如商品订购、购物车查看);而从横向结构来看,我们差点儿每一个系统又包括一些公共模块(比如权限、日志模块等)。
这些公共模块分布于我们各个核心业务之中(比如订购和查看商品明细的过程都须要检查用户权限、记录系统日志等)。这样一来不仅在开发过程中要处处关注公共模块的处理并且开发后维护起来也是十分麻烦。而有了AOP之后将应用程序中的商业逻辑同对其提供支持的通用服务进行分离,使得开发者能够很多其它的关注核心业务开发。
利用动态代理实现AOP
以下我们就以一个简单的样例来看一下AOP吧!
点击下载源代码:下载
比方说,我们如今要开发的一个应用里面有非常多的业务方法,可是,我们如今要对这种方法的运行做全面监控,或部分监控.或许我们就会在要一些方法运行前进行日志记录,我们写个样例看看我们最简单的解决方式
我们先写一个接口UserManager.java代码例如以下:
publicinterface UserManager {
publicvoid add(String userId, String userName);
}
add方法里面仅仅是将简单的字符串作为參数,而不是实体。勿怪,解说的重点不是这里。我们去写个类实现UserManager接口
publicclass UserManagerImp implements UserManager {
@Override
publicvoid add(String userId, String userName) {
System.out.println("成功运行:UserManagerImpl.add()userId-->>" + userId);
}
}
如今我们要为这个业务方法加上日志记录的业务,我们在不改变原代码的情况下,我们会去怎么做呢?或许,你会去写一个类去实现UserManager接口,并依赖UserManagerImp这个类.代码例如以下:
public class UserManagerProxyimplements UserManager{
private UserManager userManager;
public UserManagerProxy(UserManager userManager){
this.userManager= userManager;
}
publicvoid addUser(String userId, String userName) {
System.out.println("start-->>addUser()userId-->>" + userId);
try{
userManager.add(userId,userName);
System.out.println("success-->>addUser()");
}catch(Exceptione) {
e.printStackTrace();
System.out.println("error-->>addUser()");
thrownew RuntimeException();
}
}
}
从上面的代码我们能够看出,UserManager
对象是被UserManagerProxy这个所谓的代理所创建的.这样,假设我们以后要把日志记录的功能去掉.那我们仅仅要把得到userManager对象的的详细实现改为UserManager的就能够。
上面的代码 就是对AOP的最简单的实现,可是我们接下来想,假设我们要在非常多业务逻辑之前加日志的话。那么,我们是不是要去写非常多个UserManagerProxy这种类呢.事实上也是一种非常麻烦的事.在jdk1.3以后.jdk跟我们提供了一个API java.lang.reflect.InvocationHandler的类. 这个类能够让我们在JVM调用某个类的方法时动态的为些方法做些什么事.让我们把以上的代码改一下来看看效果.
我们一样的去写一个代理类.仅仅只是.让这个类去实现java.lang.reflect.InvocationHandler接口,代码例如以下:
packagecom.java.drp.pattern; importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
importjava.lang.reflect.Proxy; publicclass LogHandler implements InvocationHandler {
/**
* 要处理的对象(也就是我们要在方法前后加上业务逻辑的对象)
*/
privateObject targetObject; /**
* 动态生成方法被处理过后的对象 (写法固定)
* @param targetObject
* @return
*/
publicObject newProxyInstance(Object targetObject){
this.targetObject= targetObject;
returnProxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(), this);
} /**
*要处理的对象中的每一个方法会被此方法送去JVM调用,也就是说,要处理的对象的方法仅仅能通过此方法调用
* 此方法是动态的,不是手动调用的
*/
@Override
publicObject invoke(Object proxy, Method method, Object[] args)
throwsThrowable {
System.out.println("将要运行的方法:"+ method.getName()); System.out.print("将要运行的方法中的參数:");
for(int i = 0; i < args.length; i++) {
System.out.print(args[i]+ " ");
}
System.out.println(); Objectresult = null;
try{
//运行原来的方法之前记录日志
System.out.println(method.getName()+ "Method Start!");
//JVM通过这条语句运行原来的方法(反射机制)
result= method.invoke(targetObject, args); //运行原来的方法之后记录日志
System.out.println(method.getName()+ "Method End!");
}catch (Exception e) {
e.printStackTrace();
throwe;
}
//返回方法返回值给调用者
returnresult;
} }
该段代码的运行流程
执行结果:
将要运行的方法:add
将要运行的方法中的參数:001tch
addMethod Start!
加入用户成功
addMethod End!
从上面的样例我们看出,你的不论什么对象的方法运行之前要加上记录日志的操作都是能够的.LogHandler自己主动去代理运行被代理对象UserManagerImp中的每个方法,通过java.lang.reflect.InvocationHandler接口就把我们的代理对象和被代理对象解藕。
总结
上面简单的介绍了怎样用动态代理的方式实现AOP。主要是帮助大家理解动态代理AOP的大致思路。以便更好的使用AOP工具,而且把AOP应用到实际的面向对象开发。
版权声明:本文博主原创文章。博客,未经同意不得转载。
集装箱学习(两):动手模拟AOP的更多相关文章
- [原]容器学习(二):动手模拟AOP
简单来说,Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架.上文已经介绍模拟IoC实现,这篇文章来动手模拟AOP. AOP简述 面向对象强调"一切皆是对象" ...
- [原]容器学习(一):动手模拟spring的IoC
介绍 学习经典框架的实现原理以及设计模式在其实际中的运用,是非常有必要的,可以让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能,明白原理后,可以更好的使用它,进而为进行面向对象提供一 ...
- 容器学习(一):动手模拟spring的IoC
介绍 学习经典框架的实现原理以及设计模式在事实上际中的运用,是很有必要的,能够让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能.明确原理后,能够更好的使用它,进而为进行面向对象提供一 ...
- 动态代理学习(一)自己动手模拟JDK动态代理
最近一直在学习Spring的源码,Spring底层大量使用了动态代理.所以花一些时间对动态代理的知识做一下总结. 我们自己动手模拟一个动态代理 对JDK动态代理的源码进行分析 文章目录 场景: 思路: ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- Spring两种实现AOP的方式
有两种实现AOP的方式:xml配置文件的方式和注解的形式 我们知道通知Advice是指对拦截到的方法做什么事,可以细分为 前置通知:方法执行之前执行的行为. 后置通知:方法执行之后执行的行为. 异常通 ...
- python学习两月总结_汇总大牛们的思想_值得收藏
下面是我汇总的我学习两个月python(version:3.3.2)的所有笔记 你可以访问:http://www.python.org获取更多信息 你也可以访问:http://www.cnblogs. ...
- Java动态代理(三)——模拟AOP实现
以下案例模拟AOP实现 目录结构 接口PersonService package com.ljq.service; public interface PersonService { public vo ...
- 为U盘装备Ubuntu工作学习两不误
题记: 在上一篇文章中,我介绍了让Ubuntu 10.04完美支持Thinkpad小红点Trackpoint.看上去,显得有些不痛不痒,实际上有些同学会因为小红点中键不能正常使用,而放弃在Th ...
随机推荐
- sun.misc.BASE64Encoder找不到包,解决方法
右键项目->属性->java bulid path->jre System Library->access rules->resolution选择accessible,以 ...
- [Java Web]Struts2解决中文乱码问题
1.设置struts的字符编码,能够在struts.xml中添加下面代码: <constant name="struts.i18n.encoding" value=" ...
- 第一个Spring MVC程序
最近公司项目要开始使用Spring MVC替代Struts2了,就学习了一下Spring MVC的使用.这是第一个Spring mvc程序,分别使用xml和注解两种方式. 一.使用xml格式进行构建 ...
- 如何改变word修订模型下的视图
在Word中执行与Find.Range等相关的操作时,需对修订模式下的文档进行特殊处理. 核心知识点 Word中的 RevisionsView 属性只有两种设置:显示标记的最终状态(Final Sho ...
- 查询ID为5的数据的前后各一行数据,ID不连续
首先假如有一张表 test 那么我们要查的就是 3 和 7 这里我的思路是 用SQL Server 自带的Row_Number 函数把 ID=5 的 RowNo 查出来,因为RowNo是连续的,所以它 ...
- 浅谈JavaScript DOM编程艺术读后感和一点总结
最近工作不是很忙就想想想JavaScript的内部组成和一些要点,就是从这本书开始的.对新手来说还好,简单易懂. 简单终结下我重书中学到的一些要点. 下面都是个人学习的要点提取: 1.给自己预留退路, ...
- 登陆权限验证Session和Cookie用法及BasePage类使用
最近在做ASP.NET的项目时,接触到了登陆权限模块,所有总结了一下登陆时用到的知识和方法技巧. 如图说明:实现的效果如图,由于验证码验证比较简单这里就不介绍了 首先用代码生成器生成项目,以三层为例进 ...
- Sublime+Emmet
Sublime使用Package Control安装Emmet插件: 按Ctrl+Shift+P命令板 输入install然后选择install Package,然后输入emmet找到 Emmet C ...
- phonegap安卓环境下使用BarcodeScanner插件扫描二维码教程
由于一直在使用phoneGap来开发安卓应用,而对于原生Java小白的我最近这几天一直陷入了如何使用phonegap的BarcodeScanner插件这件事情上,可以说查遍了百度和Google,虽然只 ...
- Java 中级IO流基础及主要API编程
1. IO流基础知识,流 是字节从源到目的地的运行的轨迹,次序是有意义的, 字节会按照次序进行传递, 比如Hello World 在下图中的传递的轨迹.该图形象的解释了IO中流的概念.流中全是字节.2 ...