个人理解:
Spring AOP 与Struts 的 Interceptor 拦截器 有着一样的实现原理,即通过动态代理的方式,将目标对象与执行对象结合起来,降低代码之间的耦合度,主要运用了Proxy这个静态类,通过newProxyInstance方法将目标对象与插入对象进行结合,java中推崇面向接口编程,因此,首先创建一个接口类,定义待实现的方法
package com.spring.aop; public interface ICaculate { int add(int i,int j); int sub(int i,int j); int mul(int i,int j); int div(int i,int j); }
接着,定义实现类,实现接口中的方法
package com.spring.aop; public class Caculate implements ICaculate{ public int add(int i, int j) { int result = i + j; return result; } public int div(int i, int j) { int result = i / j; return result; } public int mul(int i, int j) { int result = i * j; return result; } public int sub(int i, int j) { int result = i - j; return result; } }
最核心的部分,建立工厂类,使用动态代理,需要实现InvocationHandler接口,在这里,定义为内部类,直接在内部类中实现Invoke方法
package com.spring.aop; import java.lang.reflect.*; import java.util.Arrays; /** * 切面:如验证、前置日志、后置日志 * 通知:切面必须完成的工作 * 目标:被通知的对象,此例为业务逻辑 * 代理:向目标对象应用通知之后创建的对象 * @author 凯 * */ public class CaculateLoggingProxy { //代理的对象 private ICaculate target; public CaculateLoggingProxy(ICaculate target) { this.target = target; } @SuppressWarnings({"unchecked" }) /** * 接口也可以定义为返回类型 */ public ICaculate getLoggingProxy(){ ICaculate proxy = null; //代理对象由哪一个类加载器加载 ClassLoader loader = target.getClass().getClassLoader(); //代理对象的类型,其中有哪些方法 Class [] interfaces = new Class[]{ICaculate.class}; InvocationHandler h = new InvocationHandler() { /** * proxy: 正在返回的那个代理对象,一般情况下,在invoke 方法中都不使用该对象 * method: 正在被调用的方法 * args: 调用方法时传入的参数 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //方法名 String methodName = method.getName(); System.out.println("begin with = ["+methodName+"] params = ["+Arrays.asList(args)+"]"); //执行方法 Object result = method.invoke(target, args); System.out.println("end with = ["+methodName+"] result = ["+result+"]"); return result; } }; proxy = (ICaculate)Proxy.newProxyInstance(loader, interfaces, h); return proxy; } }
写一个测试类,测试是否成功
package com.spring.aop; public class Main { public static void main(String[] args) { ICaculate target = new Caculate(); ICaculate proxy = new CaculateLoggingProxy(target).getLoggingProxy(); int a = proxy.add(1, 1); System.out.println(a); int b = proxy.add(1, 2); System.out.println(b); } }
输出结果:
begin with = [add] params = [[1, 1]]
end with = [add] result = [2]
2
begin with = [add] params = [[1, 2]]
end with = [add] result = [3]
3