当前位置: 首页> 教育> 大学 > 创建网站英语_武汉网站定制设计_网络外包运营公司_0元免费做代理

创建网站英语_武汉网站定制设计_网络外包运营公司_0元免费做代理

时间:2025/7/10 1:28:38来源:https://blog.csdn.net/weixin_43873121/article/details/142392414 浏览次数:0次
创建网站英语_武汉网站定制设计_网络外包运营公司_0元免费做代理

Java开发-面试题-0035-Spring代理方式有哪些

更多内容欢迎关注我(持续更新中,欢迎Star✨)

Github:CodeZeng1998/Java-Developer-Work-Note

(技术)微信公众号:CodeZeng1998

(生活)微信公众号:好锅

其他平台:CodeZeng1998好锅


Spring 中的代理方式主要有两种:JDK 动态代理CGLIB 代理。两者在 Spring AOP 和 事务管理 中都被广泛使用。下面是对这两种代理方式的详细说明:


1. JDK 动态代理

概念:

JDK 动态代理是基于 Java 的 java.lang.reflect.Proxy 类和 InvocationHandler 接口来实现的。它只针对接口进行代理,因此代理类必须实现某个接口。


工作原理:
  • JDK 动态代理通过在运行时生成一个代理类,该代理类实现了目标对象所实现的接口。
  • 当代理对象调用接口中的方法时,代理类会拦截该方法调用,并将其交由 InvocationHandler 处理。
  • InvocationHandler 中,开发者可以定义代理逻辑,例如方法执行前后增强、权限检查、事务管理等。

特点:
  • 只能代理实现了接口的类。
  • 代理是基于接口调用的,因此目标对象必须实现一个或多个接口。
  • 代理类是在运行时动态生成的,无需在编译时定义。

使用场景:

Spring 会优先选择使用 JDK 动态代理,前提是目标类有实现接口,比如通过 AOP 进行事务控制时,常见的 service 层使用的是接口。


示例代码:
public interface Service {void perform();
}public class ServiceImpl implements Service {@Overridepublic void perform() {System.out.println("Performing service operation...");}
}public class ServiceInvocationHandler implements InvocationHandler {private final Object target;public ServiceInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method execution...");Object result = method.invoke(target, args);System.out.println("After method execution...");return result;}
}public class Main {public static void main(String[] args) {Service service = new ServiceImpl();Service proxy = (Service) Proxy.newProxyInstance(service.getClass().getClassLoader(),service.getClass().getInterfaces(),new ServiceInvocationHandler(service));proxy.perform();}
}

2. CGLIB 代理

概念:

CGLIB(Code Generation Library)代理是基于底层字节码生成的代理技术。它通过扩展(继承)目标类并在运行时生成代理类来实现方法拦截。CGLIB 代理不需要目标对象实现接口,因此它可以代理任何类。


工作原理:
  • CGLIB 使用 ASM 字节码操作框架在运行时生成目标类的子类,并重写目标类中的方法来实现代理。
  • 当代理类调用被代理类的方法时,代理类通过方法拦截器(MethodInterceptor)来增强方法逻辑。

特点:
  • 能够代理没有实现接口的类,即可以代理普通的类。
  • 代理是基于子类的,代理类实际上是目标类的子类,因此不能代理 final 类以及 final 方法。
  • 性能通常比 JDK 动态代理稍高,但由于生成类字节码的开销,代理类的生成较为复杂。

使用场景:

当目标类没有实现接口时,Spring 会选择使用 CGLIB 代理,例如在纯 POJO 类或者只实现抽象类的情况下,事务管理和 AOP 增强都需要使用 CGLIB 来代理。


示例代码:
public class Service {public void perform() {System.out.println("Performing service operation...");}
}public class ServiceMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method execution...");Object result = proxy.invokeSuper(obj, args);System.out.println("After method execution...");return result;}
}public class Main {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(Service.class);enhancer.setCallback(new ServiceMethodInterceptor());Service proxy = (Service) enhancer.create();proxy.perform();}
}

3. Spring 中的代理选择机制

Spring 默认优先使用 JDK 动态代理,但如果目标对象没有实现任何接口,它会自动切换到 CGLIB 代理。具体的选择机制是:

  • 如果目标对象实现了接口,Spring 会使用 JDK 动态代理。
  • 如果目标对象没有实现接口,Spring 会使用 CGLIB 代理。

可以通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 强制 Spring 使用 CGLIB 代理,即使目标类实现了接口。


4. 代理方式的选择

  • JDK 动态代理:适合目标对象实现了接口的情况。优点是代理类轻量、生成简单,缺点是只能代理接口。
  • CGLIB 代理:适合目标对象没有实现接口或希望通过继承的方式进行代理的情况。优点是代理范围广,能够代理任何类,缺点是不能代理 final 类或 final 方法,生成代理类较复杂。

总结来看,Spring 的代理机制在灵活性和性能上都非常适合于不同的业务场景,而 JDK 动态代理和 CGLIB 各有其适用场景,开发者可以根据需要选择合适的代理方式。


以上就是本文相关的所有内容了,如果发现有误欢迎评论指正,更多内容欢迎各位关注。

在这里插入图片描述

上图是由 Pic 生成的

关键词:Iron Man


更多内容欢迎关注我(持续更新中,欢迎Star✨)

Github:CodeZeng1998/Java-Developer-Work-Note

(技术)微信公众号:CodeZeng1998

(生活)微信公众号:好锅

其他平台:CodeZeng1998好锅

关键字:创建网站英语_武汉网站定制设计_网络外包运营公司_0元免费做代理

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: