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面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》