集装箱学习(两):动手模拟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 ...
随机推荐
- autoprefixer安装或者里sass的$mixin处理浏览器前缀
Autoprefixer是一个后处理程序,不象Sass以及Stylus之类的预处理器.它适用于普通的CSS,可以实现css3代码自动补全.也可以轻松跟Sass,LESS及Stylus集成,在CSS编译 ...
- Oracle数据库使用存储过程实现分页
注:本示例来源于韩顺平[10天玩转oracle数据库]视频教程 1.创建包同时创建游标 create or replace package pagingPackage is type paging_c ...
- 【SSH三大框架】Hibernate基础第一篇:编写第一个Hibernate程序
接下来这几章节学习的是Hibernate,Hibernate的主要作用就是用来和数据库进行连接,简化了JDBC的操作. 首先,我们创建项目,然后把Hibernate的jar包和sqlserver的驱动 ...
- 购买DigtalOcean VPS 以及 连接Linux
1.DigtalOcean简介 digitalocean是一家成立于2012年的总部设置在纽约的云主机商家,眼下在荷兰的阿姆斯特丹(AMS1.AMS2).美国的纽约(NYC1.NYC2)和旧金山(SF ...
- RMAN-format变量及configuration配置项
一.FORMAT字符串替代变量使用FORMAT参数时可使用的各种替换变量,如下:%c:备份片的拷贝数(从1开始编号):%d:数据库名称:%D:位于该月中的天数 (DD):%M:位于该年中的月份 (MM ...
- for循环、穷举法和迭代
循环:初始条件,循环条件,状态改变,循环体.for(初始条件;循环条件;状态改变){ 循环体}for(int i=1;i<=10;i++){ }例子:100以内与7有关的数.求100以内所有数的 ...
- hadoop高可用集群搭建小结
hadoop高可用集群搭建小结1.Zookeeper集群搭建2.格式化Zookeeper集群 (注:在Zookeeper集群建立hadoop-ha,amenode的元数据)3.开启Journalmno ...
- mysql数据库 数据类型
char(m) 固定长度字符串,m<=255:处理速度快: varchar(m) 可变长度字符串,m<=255: int(m) 整数型,-214783647到214783648之间,使用u ...
- input添加邮箱的时候自动显示后缀
1.HTML代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...
- css3圆角讲解
Css3圆角讲解:想必大家对于图片,背景圆角,都不陌生吧, 圆角语法:border-radius:圆角值: 这个值可以使用:em ,ex,pt,px,百分比; Border-radius跟margin ...