原文地址
我只是供自己使用 要理解还是看原文好
//动态代理的测试类
public interface HelloWorld {
public String sayHello();
}
实现我们的接口
public class HelloWorldImpl implements HelloWorld{
@Override
public String sayHello() {
System.out.println("hello proxy");
return "你好动态代理";
}
}
这个是jdk实现动态代理需要实现的类
public class JDKProxyHelloWorld implements InvocationHandler {
private Object target;
public Object bind(Object obj){
target=obj;
return Proxy.newProxyInstance(
//得到被代理类的类加载器
obj.getClass().getClassLoader(),
//得到被代理类的接口
obj.getClass().getInterfaces(),
//代理类
this);
}
@Override//proxy就是代理对象,就是bind方法中返回的对象 method是当前调度的方法也可以说是真实对象的方法 args就是调度方法的参数
public Object invoke(Object proxy, Method method, Object[] args){
Object o=null;
System.out.println("代理之前");
System.out.println(proxy.getClass().getName());
try {
o =method.invoke(target, args);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("代理之后");
return o;
}
}
这是main函数 我们可以看出它直接调用bind函数 通过它的接口和类加载器 以及代理类 生成了代理对象
调用代理对象的方法它 代理对象的里面实现了再方法之前执行了我们的方法 它是使用了类似我们的类加载器 再将类化为.class文件的时候 里面添加了我们的invoke方法
public class Main {
public static void main(String[] args){
//jdk的动态代理的使用
HelloWorld proxy=(HelloWorld)new JDKProxyHelloWorld().bind(new HelloWorldImpl());
//这里使用的是代理对象
Object o=proxy.sayHello();
System.out.println(o);
}
}
public final class $Proxy0 extends Proxy implements UserService {
//省略部分代码
private static Method m3;
public $Proxy0(InvocationHandler h) throws {
super(h);
}
//代理类的add 方法
public final void sayHello() throws {
try {
//调用 InvocationHandler 的invoke方法
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m3 = Class.forName("com.study.spring.proxy.jdk.UserService").getMethod("add", new Class[0]);
//省略部分代码
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
接下来我们看一看cglib的实现
public class CglibProxy implements MethodInterceptor {
public Object getProxy(Class clazz){
Enhancer enhancer=new Enhancer();//增强器
enhancer.setSuperclass(clazz);//设置超类对象 cglib代理实现的类 是继承了我们传入的类 而不是想jdk的实现了对应类的接口
enhancer.setCallback(this);//回调函数
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("begin-------"+method.getName()+"----------------------");
Object result= methodProxy.invokeSuper(o,objects);
System.out.println("end-------"+method.getName()+"----------------------");
return result;
}
}
public class CglibProxyTest {
public static void main(String[] args){
//生成代理类到本地
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "com/study/spring/proxy/cglib");
UserServiceImpl service = new UserServiceImpl();
CglibProxy cp = new CglibProxy();
UserService proxy = (UserService) cp.getProxy(service.getClass());
proxy.add();
}
}
生成的字节码文件 我们可以明显的看出 它再调用我们的add方法的时候 首先调用了我们设置的callback函数 先将callBack函数中的方法执行了再继续执行 设置的call函数就是我们之前的intercept方法 aop多重应用就只是一层一层的将代理封装了而已
public class UserServiceImpl$$EnhancerByCGLIB$$d166e24d extends UserServiceImpl implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$add$0$Method;
private static final MethodProxy CGLIB$add$0$Proxy;
final void CGLIB$add$0() {
super.add();
}
public final void add() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
var10000.intercept(this, CGLIB$add$0$Method, CGLIB$emptyArgs, CGLIB$add$0$Proxy);
} else {
super.add();
}
}
public UserServiceImpl$$EnhancerByCGLIB$$d166e24d() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
UserServiceImpl$$EnhancerByCGLIB$$d166e24d var1 = (UserServiceImpl$$EnhancerByCGLIB$$d166e24d)var0;
if(!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if(var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if(CGLIB$STATIC_CALLBACKS == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
UserServiceImpl$$EnhancerByCGLIB$$d166e24d var10000 = new UserServiceImpl$$EnhancerByCGLIB$$d166e24d;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}