JDBC动态代理
对动态代理的原理的解释
重要参考
对生成代理对象和方法调用的过程分析
-
1.调用Proxy.newProxyInstance()方法动态生成代理对象
在这个过程我们传入了目标类的类加载器(即被代理类)和代理类需要实现的接口数组。JDK使用一种称为“字节码技术”的方法来生成代理类的字节码。
1.JDK使用提供的类加载器加载生成的代理类的字节码,并通过反射创建一个代理类的实例。这个实例就是最终的动态代理对象。
2.将InvocationHandler实现与代理对象关联:在创建动态代理对象时,JDK会将你提供的InvocationHandler实现对象与代理对象关联起来。这样,当代理对象上的方法被调用时,就会调用InvocationHandler的invoke方法。 -
2.当代理对象调用方法时分析
jdk自动将我们的代理对象和InvocationHandler接口的实现类相关联起来了,当我们调用代理对象中的方法的时候将会自动调用实现类中重写的
invoke方法,实现方法增强
动态生成的代理类的脑补实现(示意图,无法执行)
- 动态生成的代理类我们看不到类,但是我们可以分析一下他的组成结构
package com.itheima.domain;
public class LeaderProxy implements IWork{
//关联InvocationHandler接口的实现类
WorkInvocationHandler handler = new WorkInvocationHandler();
@Override
public void meeting() {
//将方法调用转发给WorkInvocationHandler中的invoke方法
//传入动态生成的代理对象
//代理的方法
//方法需要的参数
return handler.invoke(proxy,method,args);
}
@Override
public int evaluate(String name) {
//将方法调用转发给WorkInvocationHandler中的invoke方法
//传入动态生成的代理对象
//代理的方法
//方法需要的参数
return handler.invoke(proxy,method,args);
}
}
发现和静态代理相比
- 1.静态代理关联被代理类,增强部分在代理类中写
- 2.动态代理类,关联InvocationHandler接口的实现类,InvocationHandler接口的实现类关联被代理类,增强部分在实现类中写
但是动态代理类在间接上是管理被代理类的,增强部分间接是在动态代理类中写的。所以本质上代理类和动态代理类是一样的
package com.proxy;
public interface UserDao {
//计算2个整数的和
public void add ();
}
package com.proxy;
public class UserDaoImpl implements UserDao{
@Override
public void add() {
System.out.println("被增强方法执行");
}
}
package com.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//代理类实现InvocationHandler接口
public class UserDaoImplProxy implements InvocationHandler {
//被代理类的对象
private Object obj;
//将被代理类的对象传递进来
public UserDaoImplProxy(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置增强....");
//被增强的方法执行
final Object res = method.invoke(obj, args);
System.out.println("后置增强.....");
return res;
}
}
package com.proxy;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
//被代理类的接口(参数二)
Class[] interfaces = {UserDao.class};
//实现InvocationHandler接口的代理类
UserDaoImpl userDaoImpl = new UserDaoImpl();
final UserDao proxyInstance =
(UserDao) Proxy.newProxyInstance(UserDao.class.getClassLoader(), interfaces, new UserDaoImplProxy(userDaoImpl));
proxyInstance.add();
}
}