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:这个方法调用时外界传入的参数值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("这是动态代理");
Object result = null;
try {
logUtils.logStart(method, args);
//利用反射执行目标方法
result = method.invoke(calculator, args);
logUtils.logReturn(method, result);
} catch (Exception e) {
// TODO: handle exception
logUtils.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);
}
}