原始代码的写法

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

有一个接口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 3512: DZY Loves Math IV [杜教筛]

    3512: DZY Loves Math IV 题意:求\(\sum_{i=1}^n \sum_{j=1}^m \varphi(ij)\),\(n \le 10^5, m \le 10^9\) n较小 ...

  2. BZOJ 2707: [SDOI2012]走迷宫 [高斯消元 scc缩点]

    2707: [SDOI2012]走迷宫 题意:求s走到t期望步数,\(n \le 10^4\),保证\(|SCC| \le 100\) 求scc缩点,每个scc高斯消元,scc之间直接DP 注意每次清 ...

  3. zlib库VS2015编译步骤

    [点击这里下载zlib1.2.8源码](http://zlib.net/zlib128.zip) [点击这里下载zlib1.2.8编译动态库](http://zlib.net/zlib128-dll. ...

  4. linear-grident的属性和使用

    css3新增Gradient属性,用来增加渐变的效果,渐变分为线性渐变 linear-grident 和 径向渐变 radial-grident,这篇文章主要介绍线性渐变linear-grident ...

  5. 企业Nginx+Keepalived双主架构案例实战

    通过上一次课程的学习,我们知道Nginx+keepalived主从配置,始终有一台服务器处于空余状态,那如何更好的利用起来呢,我们需要借助Nginx+keepalived双主架构来实现,如下图通过改装 ...

  6. java泛型类的继承规则

    首先看一看java泛型类的使用: /** * 一个泛型方法:使程序更加安全 * 并且能被更多的使用 * @author 丁** * * @param <T> */ class Pair&l ...

  7. JDBCTemplate与模板设计方法(二)

    前言:上一篇博客介绍了模板方法模式,并且给出了一个小demo,简单对模板方法进行了实现,接下来我们把目光转向spring的源码JDBCTemplate,看一看spring是如何对jdbc进行高度封装的 ...

  8. 排序算法(Java实现)

    这几天一直在看严蔚敏老师的那本<数据结构>那本书.之前第一次学懵懵逼逼,当再次看的时候,发觉写的是非常详细,非常的好. 那就把相关的排序算法用我熟悉的Java语言记录下来了.以下排序算法是 ...

  9. Ubantu16.04 redis安装

    通过FTP方式将redis的安装包从windows上传到linux上 解压命令:$sudo tar -zxf ~/Downloads/redis-3.2.7.tar.gz -C /usr/local ...

  10. 基于jquery的城市选择插件

    城市选择插件的难度不是很大,主要是对dom节点的操作.而我写的这个插件相对功能比较简答,没有加入省市联动. 上代码好了,参照代码的注释应该比较好理解. /* *基于jquery的城市选择插件 *aut ...