AOP是面向切面编程。全称:AspectOriented Programming
面向切面编程指的是:程序是运行期间,动态地将某段代码插入到原来方法代码的某些位置中。这就叫面向切面编程。
一个简单计算数功能加日记准备计算器相关类 计算接口 publicinterface Calculate { publicint add(int num1, int num2);
publicint mul(int num1, int num2);
publicint div(int num1, int num2);
publicint sub(int num1, int num2); }
计算机类 publicclass Calculator implements Calculate { publicint add(int num1, int num2) { System.out.println("日记 :【add】方法调用前 。参数1是:" + num1 + " , 参数2是:" + num2); return num1 + num2; }
publicint mul(int num1, int num2) { System.out.println("日记 :【mul】方法调用前 。参数1是:" + num1 + " , 参数2是:" + num2); return num1 * num2; }
publicint div(int num1, int num2) { System.out.println("日记 :【div】方法调用前 。参数1是:" + num1 + " , 参数2是:" + num2); return num1 / num2; }
publicint sub(int num1, int num2) { System.out.println("日记 :【sub】方法调用前 。参数1是:" + num1 + " , 参数2是:" + num2); return num1 - num2; } }
测试的代码 publicclass CalculatorTest { publicstaticvoid main(String[] args) { Calculate calculate = new Calculator(); int result =calculate.add(12, 12); System.out.println("相加的结果:" + result);
result = calculate.mul(12, 12); System.out.println("相乘的结果:" + result); } }
上面这种方法加日记处理操作。日记的代码就会耦合到业务代码中。而且后期如果需要修改日记就需要去指的修改所有方法中的日记操作。这个维护操作非常不方便。 可以说是一个很失败的例子。 |
原始方法统一日记处理。把日记的内容封装到一个类去中集中处理。
编写一个日记处理工具类 publicclass LogUtil { publicstaticvoid log(String method, int num1, int num2) { System.out.println("日记 :【" + method + "】 方法调用前 。参数1是:" + num1 + " , 参数2是:" + num2); } }
修改原来Calculator中的日记代码 @Override publicint add(int num1, int num2) { LogUtil.log("add", num1, num2); return num1 + num2; }
@Override publicint mul(int num1, int num2) { LogUtil.log("mul", num1, num2); return num1 * num2; }
但是这种方式的不足之处是,每有一个需要加日记的类,都需要到类的代码中去添加日记功能代码。 无法做到所有对象都统一处理。 |
使用代理实现日记
使用jdk动态代理统一日记创建一个计算器代理工具类 publicclass CalculateProxyFactory {
publicstatic CalculategetProxy(Calculate target) { // 定义一个计算器拦截处理类 classCalculateInvocationHandler implements InvocationHandler{ Calculate target;
publicCalculateInvocationHandler(Calculate calculate) { this.target = calculate; }
/** * proxy 代理对象 * method 调用的方法 * args 方法的参数 */ @Override public Object invoke(Object proxy, Method method,Object[] args) throws Throwable { if(method.getDeclaringClass().equals(Object.class)) { return method.invoke(target, args); } LogUtil.log(method.getName(),(int) args[0], (int) args[1]); Object result = null; try { result = method.invoke(target, args); System.out.println("后置日记"); } catch (Exception e) { System.out.println("异常日记"); } finally { System.out.println("finally日记"); } return result; } }
return (Calculate) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass() .getInterfaces(), newCalculateInvocationHandler(target)); }
}
修改原来计算器中的日记代码 publicclass Calculator implements Calculate { @Override publicint add(int num1, int num2) { return num1 + num2; }
@Override publicint mul(int num1, int num2) { return num1 * num2; }
@Override publicint div(int num1, int num2) { return num1 / num2; }
@Override publicint sub(int num1, int num2) { return num1 - num2; } }
测试代码调整 publicstaticvoid main(String[] args) { Calculatecalculate = CalculateProxyFactory.getProxy(new Calculator() ); int result = calculate.add(12,12); System.out.println("相加的结果:" + result);
result= calculate.mul(12, 12); System.out.println("相乘的结果:" + result); }
优点:这种方式已经解决我们前面所有日记需要的问题。非常的灵活。而且可以方便的在后期进行维护和升级。 缺点:当然使用jdk动态代理,需要有接口。如果没有接口。就无法使用jdk动态代理。 |
使用cglib代理
publicclass CGLibProxyFactory implements MethodInterceptor {
publicstatic ObjectgetCGLibProxy(Object target, Callback callback) { // 创建一个CGLig生成器 Enhancerenhancer = new Enhancer(); // 设置父类。因为cglib是通过类,进行代码,不是通过接口 enhancer.setSuperclass(target.getClass()); // 设置拦截的代理方法 enhancer.setCallback(callback); // create 方法创建一个代理对象并返回 return enhancer.create(); }
@Override public Objectintercept(Object proxy, Method method, Object[] params, MethodProxymethodProxy) throws Throwable { LogUtil.log(method.getName(), (int) params[0], (int) params[1]); // 调用实际的对象的方法 // 一定要使用methodProxy对象 // 第一个参数是proxy代码对象的父类方法 Objectresult = methodProxy.invokeSuper(proxy, params); System.out.println("这是后置代码");
return result; }
publicstaticvoid main(String[] args) { Calculatorcalculator = (Calculator) CGLibProxyFactory.getCGLibProxy(new Calculator(), |