静态代理与动态代理的区别
-
静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件
-
动态代理是在运行时动态生成的,即编译完成之后没有实际的class文件,而是在运行时动态生成类字节码 ,并加载到JVM中
-
动态代理分为:JDK动态代理和CGLib动态代理 【二者具体的区别在后面章节进行介绍】
JDK动态代理
JDK动态代理又称为接口代理,顾名思义它只能代理实现了接口的类,它是利用反射机制生成一个实现代理接口的类(这个类看不见,摸不着,在jvm内存中有这个类),在调用具体方法前调用InvokeHandler来处理。核心是实现InvokeHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知
- 接口类
public interface UserService {
void select();
void update();
}
- 目标类
public class UserServiceImpl implements UserService{
@Override
public void select() {
System.out.println("查询 selectById");
}
@Override
public void update() {
System.out.println("更新 update");
}
}
- 代理类模板 注意这里不是代理类,因为动态代理类是调用时由JVM动态生成的,所以这里只是代理类的一个模板
public class LogHandler implements InvocationHandler {
private Object target; //被代理的对象,方法的实际执行者
public LogHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object invoke = method.invoke(target, args);
after();
return invoke;
}
private void before(){
System.out.println("方法调用前");
}
private void after(){
System.out.println("方法调用后");
}
}
- 测试
public class Client {
public static void main(String[] args) {
UserService userServiceImp = new UserServiceImpl(); //被代理的对象
//获取类加载器
ClassLoader classLoader = userServiceImp.getClass().getClassLoader();
//获取所有接口的class
Class[] interfaces = userServiceImp.getClass().getInterfaces();
//创建一个将传给代理类的调用请求处理器,处理所有的代理对象上的方法调用
//这里创建的是一个自定义的日志处理器,需要传入实际的执行对象UserServiceImpl
LogHandler logHandler = new LogHandler(userServiceImp);
//创建具体的代理类
UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, logHandler);
proxy.update();
proxy.select();
}
}
方法调用前
更新 update
方法调用后
方法调用前
查询 selectById
方法调用后