参考资料:

http://www.importnew.com/15420.html
http://www.cnblogs.com/techyc/p/3455950.html

Spring是借助了动态代理(JDK dynamic proxy)和CGlib两种技术实现AOP的,本文将学习前人的例子使用动态代理模拟AOP的特性。

1. 环境

Java: jdk1.8.0_144

2. 学习动态代理Proxy.newProxyInstance()方法

它的三个参数如下

参数名 类型 说明
loader ClassLoader 被代理类的类加载器
interfaces Class<?>[] 被代理类实现的interface集合
h InvocationHandler 被代理类的所有方法调用,都会绑定到java.lang.reflect.InvocationHandler接口的invoke方法执行

3. 实现思路

  • 通过JDK dynamic proxy代理目标对象
  • 覆盖InvocationHandler的invoke方法,包装被代理对象的方法调用,动态添加逻辑来实现类似于after/before/around的AOP功能

在一定程度上,实现的思路与装饰器模式相似,它们区别在于

  • 装饰器模式中的包装类需要知道被包装类的接口细节,而这里不需要
  • 装饰器模式不需要使用反射和代理,而这里需要

4. 代码解析

https://github.com/hivsuper/study/tree/master/study-aop

  • 将被代理的类及其接口
public interface Calculator {
    public int add(int a, int b);
}
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}
  • 绑定被代理对象的调度接口
import java.lang.reflect.InvocationHandler;

public abstract class AbstractHandler implements InvocationHandler {
    private Object targetObject;

    public Object getTargetObject() {
        return targetObject;
    }

    public void setTargetObject(Object targetObject) {
        this.targetObject = targetObject;
    }
}
  • 生成代理的简单工厂
import java.lang.reflect.Proxy;
import java.util.List;

public class ProxyFactory {
    public static Object getProxy(Object targetObject, List<AbstractHandler> handlers) {
        Object proxyObject = null;
        if (handlers.size() > 0) {
            proxyObject = targetObject;
            for (AbstractHandler abstractHandler : handlers) {
                abstractHandler.setTargetObject(proxyObject);
                proxyObject = Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                        targetObject.getClass().getInterfaces(), abstractHandler);
            }
            return proxyObject;
        } else {
            return targetObject;
        }
    }
}
  • 测试类
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.lxp.study.aop.AbstractHandler;
import org.lxp.study.aop.ProxyFactory;

public class CalculatorImplTest {

    @Test
    public void testAdd() throws Exception {
        Calculator calculator = new CalculatorImpl();
        AbstractHandler before = new AbstractHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("...before...");
                return method.invoke(getTargetObject(), args);
            }
        };
        AbstractHandler after = new AbstractHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = method.invoke(getTargetObject(), args);
                System.out.println("...after...");
                return result;
            }
        };
        AbstractHandler around = new AbstractHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                StringBuilder sb = new StringBuilder();
                for (Object arg : args) {
                    sb.append(arg).append(",");
                }
                System.out.println("Parameters:" + sb.substring(0, sb.length() - 1));
                Object result = method.invoke(getTargetObject(), args);
                System.out.println("Result:" + result);
                return result;
            }
        };
        List<AbstractHandler> handlers = new ArrayList<AbstractHandler>();
        handlers.add(before);
        handlers.add(after);
        handlers.add(around);
        Calculator proxy = (Calculator) ProxyFactory.getProxy(calculator, handlers);
        Assert.assertEquals(30, proxy.add(20, 10));
    }

}

 

 posted on 2017-08-20 00:22  hiv  阅读(467)  评论(0编辑  收藏  举报