原始代码的写法

既然要通过代码来演示,那必须要有例子,这里我的例子为:

有一个接口Dao有insert、delete、update三个方法,在insert与update被调用的前后,打印调用前的毫秒数与调用后的毫秒数

首先定义一个Dao接口:

public interface Dao {

    public void insert();

    public void delete();

    public void update();

}

然后定义一个实现类DaoImpl:
public class DaoImpl implements Dao {

    @Override
public void insert() {
System.out.println("DaoImpl.insert()");
} @Override
public void delete() {
System.out.println("DaoImpl.delete()");
} @Override
public void update() {
System.out.println("DaoImpl.update()");
} }
最原始的写法,我要在调用insert()与update()方法前后分别打印时间,就只能定义一个新的类包一层,在调用insert()方法与update()方法前后分别处理一下
,新的类我命名为ServiceImpl,其实现为:
public class ServiceImpl {

    private Dao dao = new DaoImpl();

    public void insert() {
System.out.println("insert()方法开始时间:" + System.currentTimeMillis());
dao.insert();
System.out.println("insert()方法结束时间:" + System.currentTimeMillis());
} public void delete() {
dao.delete();
} public void update() {
System.out.println("update()方法开始时间:" + System.currentTimeMillis());
dao.update();
System.out.println("update()方法结束时间:" + System.currentTimeMillis());
} }

这是最原始的写法,这种写法的缺点也是一目了然:

方法调用前后输出时间的逻辑无法复用,如果有别的地方要增加这段逻辑就得再写一遍
如果Dao有其它实现类,那么必须新增一个类去包装该实现类,这将导致类数量不断膨胀。

使用AOP

最后来看一下使用AOP的方式,首先定义一个时间处理类,我将它命名为TimeHandler:

public class TimeHandler {
  public void printTime(ProceedingJoinPoint pjp) {
Signature signature = pjp.getSignature();
if (signature instanceof MethodSignature) {
MethodSignature methodSignature = (MethodSignature)signature;
Method method = methodSignature.getMethod();
System.out.println(method.getName() + "()方法开始时间:" + System.currentTimeMillis());
      try {
pjp.proceed();
System.out.println(method.getName() + "()方法结束时间:" + System.currentTimeMillis());
} catch (Throwable e) {
        e.printStackTrace();
}
}
}
}
切面方法printTime本身可以不用定义任何的参数,但是有些场景下需要获取调用方法的类、方法签名等信息,此时可以
在printTime方法中定义JointPoint,Spring会自动将参数注入,可以通过JoinPoint获取调用方法的类、方法签名等信息
。由于这里我用的aop:around,要保证方法的调用,这样才能在方法调用前后输出时间,因此不能直接使用JoinPoint,
因为JoinPoint没法保证方法调用。此时可以使用ProceedingJoinPoint,ProceedingPointPoint的proceed()方法可以保
证方法调用,但是要注意一点,ProceedingJoinPoint只能和aop:around搭配,换句话说,如果aop.xml中配置的是aop:before,
然后printTime的方法参数又是ProceedingJoinPoint的话,Spring容器启动将报错。 接着看一下ApplicationContext.xml的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
  <bean id="daoImpl" class="org.xrq.spring.action.aop.DaoImpl" />
   <bean id="timeHandler" class="org.xrq.spring.action.aop.TimeHandler" />
  <aop:config>
    <aop:pointcut id="addAllMethod" expression="execution(* org.xrq.spring.action.aop.Dao.*(..))" />
    <aop:aspect id="time" ref="timeHandler">
    <aop:before method="printTime" pointcut-ref="addAllMethod" />
    <aop:after method="printTime" pointcut-ref="addAllMethod" />
    </aop:aspect>
  </aop:config>
</beans> 测试代码很简单:
public class AopTest {

    @Test
@SuppressWarnings("resource")
public void testAop() {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/aop.xml"); Dao dao = (Dao)ac.getBean("daoImpl");
dao.insert();
System.out.println("----------分割线----------");
dao.delete();
System.out.println("----------分割线----------");
dao.update();
} }
到此我总结一下使用AOP的几个优点:

  切面的内容可以复用,比如TimeHandler的printTime方法,任何地方需要打印方法执行前的时间与方法执行后的时间,都可以使用TimeHandler的printTime方法
避免使用Proxy、CGLIB生成代理,这方面的工作全部框架去实现,开发者可以专注于切面内容本身
代码与代码之间没有耦合,如果拦截的方法有变化修改配置文件即可。

 
 
 

使用AOP的好处的更多相关文章

  1. .Net中的AOP系列之构建一个汽车租赁应用

    返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...

  2. [原创]java WEB学习笔记105:Spring学习---AOP介绍,相关概念,使用AOP,利用 方法签名 编写 AspectJ 切入点表达式

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. C# AOP框架入门

    AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.Spring框架用的核心技术就是AOP,是函数式编程的一 ...

  4. Spring学习之AOP总结帖

    AOP(面向方面编程),也可称为面向切面编程,是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP). 在进行 OOP 开发时,都是基于对组件(比如类)进行开发,然后对组件进行组 ...

  5. springMVC之AOP

    AOP(Aspect-Oriented Programming,面向切面编程) 切面(Aepect):横切关注点(跨越应用程序多个模块的功能)被模块化的对象: 通知(Advice):切面必须要完成的工 ...

  6. Spring学习(二)——Spring中的AOP的初步理解[转]

      [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...

  7. AOP和IOC理解

    在百度上看到一篇很有意思的文章,是对AOP的一种解释,如下:(摘自:百度文库的 AOP和IOC最容易理解的说明(Spring知识小计)): IOC,依赖倒置的意思, 所谓依赖,从程序的角度看,就是比如 ...

  8. spring(二) AOP之AspectJ框架的使用

    前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...

  9. JavaScript实现AOP(面向切面编程)

    什么是AOP? AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日志统计.安全控制.异常处理等.把这些功能抽离出来之后, 再通过" ...

随机推荐

  1. BZOJ 1396&&2865 识别子串[后缀自动机 线段树]

    Description 在这个问题中,给定一个字符串S,与一个整数K,定义S的子串T=S(i, j)是关于第K位的识别子串,满足以下两个条件: 1.i≤K≤j. 2.子串T只在S中出现过一次. 例如, ...

  2. Python tutorial阅读之Python基本运算与基本变量

    将 Python 当做计算器 除法运算 用/表示除法运算时,一般得到的是浮点数,如果我们需要得到整数,可以用运算符// 余数计算 % 幂乘方 系统内置变量_ 内置变量_,存储了最近的结果.如图 字符串 ...

  3. JavaScript之父谈JavaScript

    本文翻译自popularity,为了更好的阅读我把部分内容进行了增删改,如果你英语比较好,建议直接阅读原文,因为这篇文章是我通过google翻译再进行修改的. 貌似(根据一位精神导师的说法)JavaS ...

  4. 构建企业级Nginx+Keepalived集群架构

    随着Nginx在国内的发展潮流,越来越多的互联网公司都在使用Nginx. Nginx高性能.稳定性成为IT人士青睐的http和反向代理服务器,今天我们来实战构建Nginx+Keepalived高可用架 ...

  5. [Python Study Notes]批量将ppt转换为pdf v1.0

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...

  6. CSS常用属性计算原理

    absolute: left.right/top.bottom 的百分比值分别根据父元素的 wdith / height 计算 margin: top /right / bottom/ left 的百 ...

  7. Xshell配置SSH秘钥登录

    秘钥生成 生成公钥 工具 -> 新建用户秘钥生成向导 -> 下一步 -> 点击下一步,输入密码: 点击下一步 点击保存为文件,完成. 生成私钥 工具 -> 用户秘钥管理者 选中 ...

  8. ob_start、ob_get_contents使用

    要善于ob_start.ob_get_contents使用, 比如需要ajax获取 请求页面的模板信息 这个时候用到就很便捷 ob_start(); $this->assign('config' ...

  9. C#泛型简单应用

    最近老板要在app里开展金融模块了,产品一下就丢丢丢二三十个表单下来,怎么办,赶紧写代码,有20多个表单要提交呢,得建20多个表.等等,好像这些表单很相似,公司信息,个人信息,可是还有部分不同信息怎么 ...

  10. 快速掌握Shell编程

    作者原创作品,转载请注明出处 (一)Shell编程概述 1.1 shell简述 Shell编程和JavaScript非常相似,Shell和JavaScript都是弱类型语言,同时也都是解释型语言.解释 ...