4.1 提出问题
情景:数学计算器器
●要求
①执行加减乘除运算
②日志:在程序执行期间追踪正在发生的活动
③验证:希望计算器只能处理正数的运算
●常规实现
●问题
○代码混乱:越来越多的非业务需求(日志和验证等)加入后,原有的业务方法急剧膨胀。每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点。
○代码分散: 以日志需求为例,只是为了满足这个单一需求,就不得不在多个模块(方法)里多次重复相同的日志代码。如果日志需求发生变化,必须修改所有模块。
4.2 动态代理
代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
public class logUtils {public static void logStart(Method method,Object... args) {System.out.println("【" + method.getName() + "】方法开始执行,使用参数列表【" + Arrays.asList(args) + "】");}public static void logReturn(Method method,Object result) {System.out.println("【" + method.getName() + "】方法执行完成,计算结果是:" + result);}public static void logException(Method method, Exception e) {System.out.println("【" + method.getName() + "】方法出现了异常,异常信息是:" + e.getCause() );}public static void logEnd(Method method) {System.out.println("【" + method.getName() + "】方法最终结束了" );}}
package com.hao.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.Arrays;import com.hao.inter.Calculator;import com.hao.utils.logUtils;public class CalculatorProxy {/*** 为传入的对象创建一个动态代理对象* @param calculator* @return** Calculator calculator:被代理对象*/public static Calculator getProxy(Calculator calculator) {//方法执行器。帮我们目标对象执行目标方法InvocationHandler h = new InvocationHandler() {/*** Object proxy:代理对象:给jdk使用,任何时候都不要动这个对象* Method method:当前将要执行的目标对象的方法* Object[] args:这个方法调用时外界传入的参数值*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stubSystem.out.println("这是动态代理");Object result = null;try {logUtils.logStart(method, args);//利用反射执行目标方法result = method.invoke(calculator, args);logUtils.logReturn(method, result);} catch (Exception e) {// TODO: handle exceptionlogUtils.logException(method,e);}finally {logUtils.logEnd(method);}return result;}};//获取类加载器ClassLoader loader = calculator.getClass().getClassLoader();//获取实现的所有接口Class<?>[] interfaces = calculator.getClass().getInterfaces();//Proxy为目标对象创建代理对象;Object proxy = Proxy.newProxyInstance(loader, interfaces, h);return (Calculator)proxy;}}
public class AOPTest {
@Test
public void test() {
Calculator calculator = new MyMathCalculator();
Calculator proxy = CalculatorProxy.getProxy(calculator);
proxy.add(2, 1);
proxy.div(2, 0);
}
}

