zoukankan      html  css  js  c++  java
  • Java使用动态代理实现AOP

    参考资料:

    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));
        }
    
    }
  • 相关阅读:
    SpringBoot入门学习(二)
    SpringBoot入门学习(一)
    eclipse调试程序界面简单介绍使用
    利用URLConnection来发送POST和GET请求
    查看用户所属的组
    linux下创建用户,给用户设置密码,给用户授权
    新linux系统上rz 与sz命令不可用
    pom.xml文件报错:web.xml is missing and <failOnMissingWebXml> is set to true
    MySql采用GROUP_CONCAT合并多条数据显示的方法
    Mysql计算时间差
  • 原文地址:https://www.cnblogs.com/hiver/p/7398431.html
Copyright © 2011-2022 走看看