设为首页 加入收藏

TOP

我们为什么要使用 AOP(二)
2017-10-16 10:29:33 】 浏览:10520
Tags:我们 为什么 使用 AOP
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if ("insert".equals(methodName) || "update".equals(methodName)) { System.out.println(methodName + "()方法开始时间:" + System.currentTimeMillis()); Object result = method.invoke(obj, args); System.out.println(methodName + "()方法结束时间:" + System.currentTimeMillis()); return result; } return method.invoke(obj, args); } }

其调用方式很简单,我写一个main函数:

/**
 * @author 五月的仓颉http://www.cnblogs.com/xrq730/p/7003082.html
 */
public static void main(String[] args) {
    Dao dao = new DaoImpl();
        
    Dao proxyDao = (Dao)Proxy.newProxyInstance(LogInvocationHandler.class.getClassLoader(), new Class<?>[]{Dao.class}, new LogInvocationHandler(dao));
        
    proxyDao.insert();
    System.out.println("----------分割线----------");
    proxyDao.delete();
    System.out.println("----------分割线----------");
    proxyDao.update();
}

结果就不演示了,这种方式的优点为:

  • 输出日志的逻辑被复用起来,如果要针对其他接口用上输出日志的逻辑,只要在newProxyInstance的时候的第二个参数增加Class<?>数组中的内容即可

这种方式的缺点为:

  • JDK提供的动态代理只能针对接口做代理,不能针对类做代理
  • 代码依然有耦合,如果要对delete方法调用前后打印时间,得在LogInvocationHandler中增加delete方法的判断

使用CGLIB

接着看一下使用CGLIB的方式,使用CGLIB只需要实现MethodInterceptor接口即可:

/**
 * @author 五月的仓颉http://www.cnblogs.com/xrq730/p/7003082.html
 */
public class DaoProxy implements MethodInterceptor {

    @Override
    public Object intercept(Object object, Method method, Object[] objects, MethodProxy proxy) throws Throwable {
        String methodName = method.getName();
        
        if ("insert".equals(methodName) || "update".equals(methodName)) {
            System.out.println(methodName + "()方法开始时间:" + System.currentTimeMillis());
            proxy.invokeSuper(object, objects);
            System.out.println(methodName + "()方法结束时间:" + System.currentTimeMillis());
            
            return object;
        }
        
        proxy.invokeSuper(object, objects);
        return object;
    }

}

代码调用方式为:

/**
 * @author 五月的仓颉http://www.cnblogs.com/xrq730/p/7003082.html
 */
public static void main(String[] args) {
    DaoProxy daoProxy = new DaoProxy();
    
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(DaoImpl.class);
    enhancer.setCallback(daoProxy);
        
    Dao dao = (DaoImpl)enhancer.create();
    dao.insert();
    System.out.println("----------分割线----------");
    dao.delete();
    System.out.println("----------分割线----------");
    dao.update();
}

使用CGLIB解决了JDK的Proxy无法针对类做代理的问题,但是这里要专门说明一个问题:使用装饰器模式可以说是对使用原生代码的一种改进,使用Java代理可以说是对于使用装饰器模式的一种改进,但是使用CGLIB并不是对于使用Java代理的一种改进。

前面的可以说改进是因为使用装饰器模式比使用原生代码更好,使用Java代理又比使用装饰器模式更好,但是Java代理与CGLIb的对比并不能说改进,因为使用CGLIB并不一定比使用Java代理更好,这两种各有优缺点,像Spring框架就同时支持Java Proxy与CGLIB两种方式。

从目前看来代码又更好了一些,但是我认为还有两个缺点:

  • 无论使用Java代理还是使用CGLIB,编写这部分代码都稍显麻烦
  • 代码之间的耦合还是没有解决,像要针对delete()方法加上这部分逻辑就必须修改代码

使用AOP

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

/**
 * @author 五月的仓颉http://www.cnblogs.com/xrq730/p/7003082.html
 */
public class TimeHandler {
    
    public void printTime(ProceedingJoinPoint pjp) {
        Signature signature = pjp.getSignature();
        if (signature instanceof MethodSignature) {
            MethodSignature methodSignature = (MethodSignature)signature;
            Met
首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇这些年,安放在我工位上的那些书 下一篇Redis 和 Memcached 的区别

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目