JDK动态代理详解(实现原理及使用示例)

JDK动态代理详解(实现原理及使用示例)-mikechen

JDK动态代理用于Spring动态代理等场景,应用广泛,下面我就来详解JDK动态代理的实现@mikechen

什么是动态代理

动态代理是一种在运行时生成代理类的技术,它允许我们在不修改目标对象的情况下,通过代理对象来控制目标对象的行为。

 

什么是JDK动态代理

JDK动态代理是Java语言内置的一种代理机制,它可以在运行时动态地生成代理类,实现对指定接口的代理。

也就说:JDK动态代理就是动态代理的一种实现方式,当然你也可以使用CGLib动态代理来生成。

 

JDK动态代理实现原理

JDK动态代理是基于Java的反射机制实现的,其实现原理可以分为以下几个步骤:

1.定义一个接口

首先需要定义一个接口,代理对象需要实现该接口,从而达到对目标对象的代理。

 

2.定义一个InvocationHandler接口和其实现类

InvocationHandler接口中只有一个方法invoke(),该方法会在代理对象调用方法时被执行,其中包含了对目标对象方法的增强逻辑。

InvocationHandler实现类中必须实现invoke()方法,该方法包含了对目标对象方法的增强逻辑。

 

3.使用Proxy类创建代理对象

在JDK动态代理中,代理对象的生成是通过Proxy类的静态方法newProxyInstance()实现的。

该方法会根据传入的参数动态生成代理类的字节码,并通过反射机制生成代理对象实例。

 

4.调用代理对象的方法

当代理对象调用方法时,实际上是调用了InvocationHandler接口实现类中的invoke()方法。

在invoke()方法中,可以通过反射机制调用目标对象的方法,并在调用前后添加需要执行的逻辑。

JDK动态代理的实现原理简单易懂,其核心在于代理对象的动态创建和方法调用处理程序的实现。

 

JDK动态代理使用示例

下面我就来详解JDK动态代理实现的完整过程:

1.定义一个接口UserService

表示被代理类所实现的业务接口

public interface UserService {
    void addUser(String name);
}

 

2.实现一个InvocationHandler接口,实现invoke方法

在InvocationHandler接口实现类中实现invoke方法,该接口中只有一个方法invoke,用于处理代理类的方法调用。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class UserServiceProxy implements InvocationHandler {
    private Object target;

    public UserServiceProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before method: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("after method: " + method.getName());
        return result;
    }
}

 

3.调用Proxy类的静态方法newProxyInstance创建代理对象

import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(), new UserServiceProxy(userService));
        proxy.addUser("Tom");
    }
}

该方法接受三个参数:

  • ClassLoader对象,用于加载代理类;
  • Class数组,表示被代理类所实现的业务接口;
  • InvocationHandler对象,用于处理代理类的方法调用。

以上JDK动态代理实现过程的完整代码示例,如下:

public interface UserService {
    void addUser(String name);
}

public class UserServiceImpl implements UserService {
    public void addUser(String name) {
        System.out.println("add user: " + name);
    }
}

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class UserServiceProxy implements InvocationHandler {
    private Object target;

    public UserServiceProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before method: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("after method: " + method.getName());
        return result;
    }
}

import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(), new UserServiceProxy(userService));
        proxy.addUser("Tom");
    }
}

输出:

before method: addUser
add user: Tom
after method: addUser

可以看到,在调用addUser方法前后,程序分别打印了before method: addUser和after method: addUser这两个信息,这说明我们的代理类已经成功地对目标

以上就是JDK动态代理详解,更多内容请查看:JDK动态代理与CGLib的区别(5大核心区别)

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法