动态代理原理
Spring底层用了哪些技术?(第一 工厂模式 第二 动态代理 )
// 第一个参数是: 类加载器
ClassLoader cl = App.class.getClassLoader();
// 第二个参数:字节码对象数组
// 第二个参数是字节码对象数组,表示动态代理创建出来的那个对象,自动实现了哪些接口
Class[] interfaces = new Class[]{ICalculator.class};
// 第三个参数:调用处理器
// 每当调用代理对象的方法时,都不是去执行真正的方法,而是统统进入 调用处理器 对象的invoke方法!
// 因为代理对象(所属的类)已经实现了I接口,所以可以通过代理对象调用I接口中的所有方法:
class MyHandler implements InvocationHandler {
private Object target;
public MyHandler(Object target) {
this.target = target;
}
}
ICalculator proxy = (ICalculator) Proxy.newProxyInstance(cl, interfaces, new MyHandler(c));
package com.xaeduask.k_dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import org.junit.Test;
interface ICalculator {
public int add(int a, int b);
public int sub(int a, int b);
public int mul(int a, int b);
public int div(int a, int b);
public int mod(int a, int b);
}
class CalculatorImpl implements ICalculator {
public int add(int a, int b) {
int r = a + b;
return r;
}
public int sub(int a, int b) {
int r = a -b;
return r;
}
public int mul(int a, int b) {
int r = a * b;
return r;
}
public int div(int a, int b) {
int r = a / b;
return r;
}
public int mod(int a, int b) {
int r = a % b;
return r;
}
}
class MyHandler implements InvocationHandler {
private Object target;
public MyHandler(Object target) {
this.target = target;
}
//这里又有3个参数,一会再解释
// 第一个参数proxy,就是代理对象本身
// 第二个参数是method,本次正在调用中的代理对象的方法
// 第三个参数是args,表示本次代理对象调用的方法中的参数!
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("aaa");
System.out.println(method.getName()+"开始,参数是:" + Arrays.toString(args));
// 把method代表的方法,当做target对象的方法调用,
Object r = method.invoke(target, args);
System.out.println(method.getName()+"结束,结果是:" + r);
System.out.println("bbb");
return r; // 这里的返回值,会返回到代理对象调用方法的点用处!
}
}
public class App {
@Test
public void test() throws Exception {
//创建一个目标对象(真实对象,不是代理对象)
//调用目标对象的任何方法,都调用的是真正的方法
ICalculator c = new CalculatorImpl();
// 创建代理对象,需要3个参数
// 第一个参数是: 类加载器
// 我们知道,构造器就是用来实例化对象的,其实在构造器的底层实例化对象时,会调用类加载器来实例化对象!
// 而使用动态代理也能实例化类的对象,势必也少不了底层的那个类加载器!
ClassLoader cl = App.class.getClassLoader();
// 第二个参数:字节码对象数组
// 第二个参数是字节码对象数组,表示动态代理创建出来的那个对象,自动实现了哪些接口
Class[] interfaces = new Class[]{ICalculator.class};
// 第三个参数:调用处理器
// 每当调用代理对象的方法时,都不是去执行真正的方法,而是统统进入 调用处理器 对象的invoke方法!
// 因为代理对象(所属的类)已经实现了I接口,所以可以通过代理对象调用I接口中的所有方法:
ICalculator proxy = (ICalculator) Proxy.newProxyInstance(cl, interfaces, new MyHandler(c));
int r = proxy.mod(-5, -2);
System.out.println("proxy:" + r);
}
}