返回
面试官爱问的JDK动态代理的奥秘
见解分享
2023-12-03 04:55:22
在面试中,关于Spring的代理方式的提问似乎是必不可少的。相信大家都会异口同声的回答:JDK动态代理和CGLIB动态代理。那么这两种代理方式究竟有何区别呢?
JDK动态代理是通过接口实现来创建代理对象,而CGLIB动态代理则是通过子类来实现的。接下来,我们将更深入地了解一下JDK动态代理。
一、JDK动态代理的原理
JDK动态代理是基于Java反射机制实现的。在运行时,JVM会动态创建一个实现指定接口的代理类,并生成该代理类的字节码。代理类中的方法会调用InvocationHandler接口的invoke()方法,而invoke()方法则可以调用目标对象的方法。
JDK动态代理的优点是侵入性较小,不需要修改目标对象。缺点是只能代理实现了接口的类,并且只能代理public方法。
二、JDK动态代理的应用场景
JDK动态代理可以应用于多种场景,例如:
- 日志记录:可以通过JDK动态代理在目标方法执行前后记录日志。
- 事务管理:可以通过JDK动态代理在目标方法执行前后开启和关闭事务。
- 安全控制:可以通过JDK动态代理在目标方法执行前检查用户的权限。
- 性能监控:可以通过JDK动态代理在目标方法执行前后记录性能数据。
三、JDK动态代理的注意事项
在使用JDK动态代理时,需要注意以下几点:
- 目标类必须实现接口。
- 代理类不能代理final方法。
- 代理类不能代理静态方法。
- 代理类不能代理私有方法。
四、JDK动态代理的示例代码
下面是一个JDK动态代理的示例代码:
public class JdkDynamicProxy { public static void main(String[] args) { // 目标对象 Target target = new Target(); // 代理对象 Target proxy = (Target) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理对象调用了方法:" + method.getName()); return method.invoke(target, args); } }); // 调用代理对象的方法 proxy.hello(); } } interface Target { void hello(); } class TargetImpl implements Target { @Override public void hello() { System.out.println("目标对象调用了hello方法"); } }
运行以上代码,输出结果如下:
代理对象调用了方法:hello 目标对象调用了hello方法
从输出结果可以看出,代理对象调用了目标对象的方法,并且在方法调用前后执行了代理逻辑。