Spring-代理
存在一个类,实现两个数的加减乘除功能,并想在功能实现的前后加上日志,日志内容为进行了什么操作,输出结果是什么
我们可以在每一个方法中,使用print的方式来打印日志,但这十分麻烦且有大量的冗余代码
使用代理模式来解决这个问题
1 2 3 4 5 6 7 8 9 10 11
| public interface Calculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import org.springframework.stereotype.Component;
@Component public class CalculatorPureImpl implements Calculator { @Override public int add(int i, int j) { int result = i + j; return result; } @Override public int sub(int i, int j) { int result = i - j; return result; } @Override public int mul(int i, int j) { int result = i * j; return result; } @Override public int div(int i, int j) { int result = i / j; return result; } }
|
静态代理
新建一个代理类同样实现功能接口,但代理类不做具体的功能实现,只负责日志的打印
将实现类作为代理类的属性,并在构造方法将实现类注入到代理类中
在重写的功能方法中,先打印所需要的日志,再调用实现类中的方法去完成具体的功能实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class CalculatorStaticProxy implements Calculator {
Calculator calculator = new CalculatorPureImpl();
public CalculatorStaticProxy(Calculator calculator) { this.calculator = calculator; }
@Override public int add(int i, int j) { System.out.println("i = " + i + ", j = " + j); int result = calculator.add(i, j); System.out.println("result = " + result); return result; }
@Override public int sub(int i, int j) { System.out.println("i = " + i + ", j = " + j); int result = calculator.sub(i, j); System.out.println("result = " + result); return result; }
@Override public int mul(int i, int j) { System.out.println("i = " + i + ", j = " + j); int result = calculator.mul(i, j); System.out.println("result = " + result); return result; }
@Override public int div(int i, int j) { System.out.println("i = " + i + ", j = " + j); int result = calculator.div(i, j); System.out.println("result = " + result); return result; } }
|
动态代理
JDK动态代理:JDK提供了原生的动态代理的实现方式,他必须需要被代理的实现类的接口,会根据接口动态生成一个代理对象
cglib:第三方技术(被Spring集成),通过被代理的实现类直接生成一个代理类,不需要实现类的接口
JDK动态代理
尚硅谷提供了一个基于JDK动态代理的生成工具类
和静态代理类一样,将实现类对象作为代理类的属性注入,在这里为了实现动态,类的类型是Object
Proxy.newProxyInstance()方法需要三个参数
- classLoader:实现类的类加载器
- interfaces:实现类的接口
- invocationHandler:具体的代理类的功能类,其参数需要重写抽象方法,其中具体的实现使用到反射
- 抽象方法提供了三个参数,proxy(实现类的对象),method(实现类的功能方法),args(方法所对应的参数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays;
public class ProxyFactory {
private Object target;
public ProxyFactory(Object target) { this.target = target; }
public Object getProxy(){
ClassLoader classLoader = target.getClass().getClassLoader(); Class<?>[] interfaces = target.getClass().getInterfaces(); InvocationHandler invocationHandler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null; try { System.out.println("[动态代理][日志] "+method.getName()+",参数:"+ Arrays.toString(args)); result = method.invoke(target, args); System.out.println("[动态代理][日志] "+method.getName()+",结果:"+ result); } catch (Exception e) { e.printStackTrace(); System.out.println("[动态代理][日志] "+method.getName()+",异常:"+e.getMessage()); } finally { System.out.println("[动态代理][日志] "+method.getName()+",方法执行完毕"); } return result; } }; return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); } }
|
AOP框架就是封装了动态代理技术