JDK动态代理

静态代理与动态代理的区别

  • 静态代理在编译时就已经实现,编译完成后代理类是一个实际的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
方法调用后
posted @ 2021-01-14 21:55  刘指导  阅读(103)  评论(0编辑  收藏  举报