AOP 的拦截功能是由 java 中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。
1 package com.itdoc.spring.aop.proxy; 2 3 /** 4 * http://www.cnblogs.com/goodcheap 5 * 6 * @author: Wáng Chéng Dá 7 * @create: 2017-03-03 19:34 8 */ 9 public interface Arithmetic { 10 11 int add(int i, int j); 12 13 int sub(int i, int j); 14 15 int mul(int i, int j); 16 17 int div(int i, int j); 18 19 }
1 package com.itdoc.spring.aop.proxy; 2 3 /** 4 * http://www.cnblogs.com/goodcheap 5 * 6 * @author: Wáng Chéng Dá 7 * @create: 2017-03-03 19:35 8 */ 9 public class ArithmeticProxyImpl implements Arithmetic { 10 @Override 11 public int add(int i, int j) { 12 int result = i + j; 13 return result; 14 } 15 16 @Override 17 public int sub(int i, int j) { 18 int result = i - j; 19 return result; 20 } 21 22 @Override 23 public int mul(int i, int j) { 24 int result = i * j; 25 return result; 26 } 27 28 @Override 29 public int div(int i, int j) { 30 int result = i / j; 31 return result; 32 } 33 }
1 package com.itdoc.spring.aop.proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 import java.util.Arrays; 7 8 /** 9 * http://www.cnblogs.com/goodcheap 10 * 11 * @author: Wáng Chéng Dá 12 * @create: 2017-03-03 19:45 13 */ 14 public class ArithmeticProxyHandle { 15 16 //要代理的对象 17 private Arithmetic target; 18 19 public ArithmeticProxyHandle(Arithmetic target) { 20 this.target = target; 21 } 22 23 public ArithmeticProxyHandle() { 24 } 25 26 public Arithmetic getLoggingProxy() { 27 Arithmetic proxy = null; 28 //代理对象由哪个类加载器负责加载 29 ClassLoader loader = target.getClass().getClassLoader(); 30 //代理对象的类型, 即其中有哪些方法 31 Class [] interfaces = new Class[]{Arithmetic.class}; 32 //当调用代理对象中的方法时, 执行该代码 33 InvocationHandler h = new InvocationHandler() { 34 /** 35 * 36 * @param proxy 正在返回的那个代理对象, 一般情况下, 在 invoke 方法中都不使用该对象。 37 * @param method 正在被调用的方法。 38 * @param args 调用方法时, 传入的参数。 39 * @return 40 * @throws Throwable 41 */ 42 @Override 43 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 44 String name = method.getName(); 45 System.out.println("The method " + name + " begins with" + Arrays.asList(args)); 46 Object result = method.invoke(target, args); 47 System.out.println("The method " + name + "ends with " + result); 48 return result; 49 } 50 }; 51 proxy = (Arithmetic) Proxy.newProxyInstance(loader, interfaces, h); 52 return proxy; 53 } 54 }
1 package com.itdoc.spring.aop.proxy; 2 3 4 /** 5 * http://www.cnblogs.com/goodcheap 6 * 7 * @author: Wáng Chéng Dá 8 * @create: 2017-03-03 19:42 9 */ 10 public class Main { 11 12 public static void main(String[] args) { 13 Arithmetic arithmetic = new ArithmeticProxyImpl(); 14 arithmetic = new ArithmeticProxyHandle(arithmetic).getLoggingProxy(); 15 16 int result = arithmetic.add(1, 2); 17 System.out.println(result); 18 result = arithmetic.sub(3, 2); 19 System.out.println(result); 20 21 } 22 }
控制台输出:
The method add begins with[1, 2] |
动态代理实现前置通知 , 后置通知 , 返回通知 , 异常通知:
1 package com.itdoc.spring.aop.proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 import java.util.Arrays; 7 8 /** 9 * http://www.cnblogs.com/goodcheap 10 * 11 * @author: Wáng Chéng Dá 12 * @create: 2017-03-03 19:45 13 */ 14 public class ArithmeticProxyHandle { 15 16 //要代理的对象 17 private Arithmetic target; 18 19 public ArithmeticProxyHandle(Arithmetic target) { 20 this.target = target; 21 } 22 23 public ArithmeticProxyHandle() { 24 } 25 26 public Arithmetic getLoggingProxy() { 27 Arithmetic proxy = null; 28 //代理对象由哪个类加载器负责加载 29 ClassLoader loader = target.getClass().getClassLoader(); 30 //代理对象的类型, 即其中有哪些方法 31 Class [] interfaces = new Class[]{Arithmetic.class}; 32 //当调用代理对象中的方法时, 执行该代码 33 InvocationHandler h = new InvocationHandler() { 34 /** 35 * 36 * @param proxy 正在返回的那个代理对象, 一般情况下, 在 invoke 方法中都不使用该对象。 37 * @param method 正在被调用的方法。 38 * @param args 调用方法时, 传入的参数。 39 * @return 40 * @throws Throwable 41 */ 42 @Override 43 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 44 String name = method.getName(); 45 Object result = null; 46 try { 47 //前置通知 48 System.out.println("The method " + name + " begins with" + Arrays.asList(args)); 49 //执行方法 50 result = method.invoke(target, args); 51 //返回通知 52 System.out.println("The method " + name + " ends with " + result); 53 } catch (Exception e) { 54 Throwable ex = new Throwable("出现异常", e); 55 //异常通知 56 System.out.println("The method " + name + " exception with " + ex); 57 } finally { 58 //后置通知 59 System.out.println("The method " + name + " ends"); 60 } 61 return result; 62 } 63 }; 64 proxy = (Arithmetic) Proxy.newProxyInstance(loader, interfaces, h); 65 return proxy; 66 } 67 }