使用AOP的好处

ConvertMe 2018-03-08 原文

使用AOP的好处

原始代码的写法

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

有一个接口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生成代理,这方面的工作全部框架去实现,开发者可以专注于切面内容本身
代码与代码之间没有耦合,如果拦截的方法有变化修改配置文件即可。

 
 
 
posted on 2018-03-08 20:53 何广鹏 阅读() 评论() 编辑 收藏

 

 
版权声明:本文为ConvertMe原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/ConvertMe/p/8530776.html

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

随机推荐

  1. Apache java项目全介绍 – 似非而是

    Apache java项目全介绍 Jakarta项目是ASF(The Apache Software Foun […]...

  2. Android页面跳转和数据传递

    Android应用开发-页面跳转和数据传递 Activity Android四大组件之一 可以理解为Andro […]...

  3. Eclipse和MyEclipse使用技巧–MyEclipse下创建的项目导入到Eclipse中详细的图文配置方法

    一、情景再现。   有些人比较喜欢用Myeclipse开发,有些人却比较喜欢用eclipse开发。但是其中有一 […]...

  4. 斗鱼直播源解析工具

    前天在网上搜抓取斗鱼直播源的时候,搜到了一个帖子(点击进入原贴).我按照楼主的方法试了一下用手机端X浏览器抓取 […]...

  5. 推荐10款免费开源的网店系统

    http://www.25gx.com/wl2009/new-260.html  ShopEx — […]...

  6. CreateEvent的用法

    事件对象就像一个开关:它只有两种状态—开和关。当一个事件处于”开”状态,我们称其为”有信号”否则称 […]...

  7. My97DatePicker日期控件,开始时间不能大于结束时间,结束时间不能小于开始时间

    在只做项目的时候,需要用到一个日期控件,之前用到过my97,感觉挺好的,兼容性很强,配置也比较容易   当开始 […]...

  8. MySQL多版本并发控制机制(MVCC)-源码浅析

    MySQL多版本并发控制机制(MVCC)-源码浅析 前言 作为一个数据库爱好者,自己动手写过简单的SQL解析器 […]...

展开目录

目录导航