动态代理-数学计算器
项目目录
1.要求
1)计算器能够执行加减乘除运算
2)日志:在程序执行期间追踪正在发生的活动
3)验证:希望计算器只能处理正数的运算
2.常规实现
**MathI.java**
package com.atguigu.proxy;
public interface MathI {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
MathImpl.java
package com.atguigu.proxy;
public class MathImpl implements MathI{
@Override
public int add(int i, int j) {
System.out.println("method:add,arguments:" + i + "," + j);
System.out.println("method:add,results:" + (i + j));
return i + j;
}
@Override
public int sub(int i, int j) {
System.out.println("method:sub,arguments:" + i + "," + j);
System.out.println("method:sub,results:" + (i - j));
return i - j;
}
@Override
public int mul(int i, int j) {
System.out.println("method:mul,arguments:" + i + "," + j);
System.out.println("method:mul,results:" + (i * j));
return i * j;
}
@Override
public int div(int i, int j) {
System.out.println("method:div,arguments:" + i + "," + j);
System.out.println("method:div,results:" + (i / j));
return i / j;
}
}
常规实现方法存在的问题
①代码混乱:越来越多的非业务需求(日志和验证等)加入后,原有的业务方法急剧膨胀。每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点。
②代码分散: 以日志需求为例,只是为了满足这个单一需求,就不得不在多个模块(方法)里多次重复相同的日志代码。如果日志需求发生变化,必须修改所有模块。
3.动态代理
MathI.java(与2中的代码相同)
MathImpl.java(2中的代码中去掉日志信息)
MyLogger.java(日志类)
ProxyUtil.java(代理类)
package com.atguigu.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class ProxyUtil{
//代理模式:1、静态代理(代理对象真实存在,是自己写好的) 2、动态代理(动态生成代理对象,不需要自己写)
private MathImpl mathImpl;//目标对象 目标对象类必须实现接口
public ProxyUtil(MathImpl mathImpl) {
super();
this.mathImpl = mathImpl;
}
public Object getProxy(){
//获取当前类的类加载器用来加载代理对象所属类
ClassLoader loader = this.getClass().getClassLoader();//动态生成代理对象就需要动态代理类,代理类的执行需要类加载器
//获取目标对象实现的所有接口的Class,代理类会和目标对象实现相同的接口,最终通过代理对象实现功能
Class[] interfaces = mathImpl.getClass().getInterfaces();
return Proxy.newProxyInstance(loader, interfaces, new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理对象实现功能的方式
try{
MyLogger.before(method.getName(), Arrays.toString(args));
Object result = method.invoke(mathImpl, args);//动态代理对象实现功能(调用目标对象的方法)
MyLogger.after(method.getName(), result);
return result;
}catch (Exception e){
MyLogger.throwing();
e.printStackTrace();
}finally{
System.out.println("哪都有我");
}
return null;
}
});
}
}
Test.java(测试类)
package com.atguigu.proxy;
public class Test {
public static void main(String[] args) {
// MathI math = new MathImpl();
// int result = math.add(1, 1);
// System.out.println(result);
ProxyUtil proxy = new ProxyUtil(new MathImpl());
MathI math = (MathI)proxy.getProxy();
int i = math.add(1, 1);
System.out.println(i);
int j = math.div(4, 0);
System.out.println(j);
}
}