当前位置: 首页 > news >正文

Spring Boot代理问题

在 Spring Boot 2.x 中,AOP(面向切面编程)默认使用 CGLIB(Code Generation Library)来实现类的代理。CGLIB 代理是通过在运行时生成目标类的子类来增强目标类的方法。这种方式允许对没有实现接口的类进行代理。以下是一些原因和机制解释,说明为什么 Spring 在 AOP 中默认使用 CGLIB。

为什么默认使用 CGLIB

  1. 可用性和兼容性

    • 不依赖于接口:CGLIB 代理不需要目标类实现接口,因此它可以代理任何类,包括那些没有实现接口的类。这在某些情况下非常方便和必要。
    • Spring 选择的默认策略:由于 CGLIB 代理在更多场景中更为通用和强大,因此它被设置为默认的代理方式。
  2. 避免困惑

    • 一致性:使用 CGLIB 可以避免开发人员在决定是否需要实现接口时遇到的困惑。无论类是否实现接口,都可以使用相同的代理机制。
  3. 性能

    • 性能优化CGLIB 的性能已经过优化,足以满足大多数企业级应用的需求。虽然 JDK 动态代理在某些情况下可能略快,但差异通常对最终用户应用程序的性能没有显著影响

Spring AOP 代理机制

Spring AOP 支持两种主要的代理模式:

  1. JDK 动态代理

    • 依赖于 java.lang.reflect.Proxy,只能对实现了一个或多个接口的类进行代理。
    • 适用于所有实现接口的类。
  2. CGLIB 代理

    • 使用 net.sf.cglib.proxy 包进行代理,通过生成目标类的子类来实现方法增强。
    • 适用于没有实现接口的类,或者可以覆盖具体类的方法以实现更广泛的应用。

如何配置代理类型

虽然 Spring 默认使用 CGLIB,但开发人员可以通过配置来控制代理类型。使用 @EnableAspectJAutoProxy 注解可以指定代理方式:

  • 默认代理设置(通常是 CGLIB):
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}

复制

  • 强制使用 CGLIB 代理
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class AppConfig {
}

复制

  • 强制使用 JDK 动态代理(仅对实现接口的类有效):
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@EnableAspectJAutoProxy(proxyTargetClass=false)
public class AppConfig {
}

复制

自动代理选择机制

Spring 会基于以下规则自动选择适合的代理机制:

  1. 如果目标类实现了至少一个接口,并且 proxyTargetClass 设置为 false

    • Spring 使用 JDK 动态代理。
  2. 如果目标类没有实现任何接口,或者 proxyTargetClass 设置为 true

    • Spring 使用 CGLIB 代理。

使用 AOP 的常见配置和限制

  1. 非公开方法

    • CGLIB 可以代理非公共方法(protectedpackage-private 和 private),而 JDK 动态代理只能代理公共接口的方法。
  2. 构造函数代理

    • CGLIB 在生成子类时会覆盖构造函数,而 JDK 动态代理则不涉及构造函数。

示例代码

以下是一个使用 CGLIB 代理的示例:

定义目标类(没有实现任何接口)
import org.springframework.stereotype.Component;@Component
public class MyService {public void doSomething() {System.out.println("Doing something...");}
}
定义切面类
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class MyAspect {@Before("execution(* com.example.MyService.doSomething(..))")public void beforeDoSomething() {System.out.println("Before advice is being applied...");}
}
配置类
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // 强制使用 CGLIB 代理
public class AppConfig {
}

总结

Spring Boot 2.x 默认使用 CGLIB 来实现 AOP 代理,主要是因为 CGLIB 适用于更广泛的场景,包括那些没有实现接口的类。此外,Spring 允许通过配置来选择和控制代理类型,以适应特定应用程序的需求和设计。

了解这些机制和配置选项,有助于开发人员在使用 Spring AOP 时做出更明智的选择,并确保代理行为符合预期。


http://www.mrgr.cn/news/65504.html

相关文章:

  • k8s 上如何跑 Dolphins 模型
  • ubuntu常用基本指令简记
  • VsCode显示空格
  • Vivo手机怎样才能投屏到别的安卓手机上去?
  • 广东网站设计提升你网站在搜索引擎中的排名
  • C语言案例——青蛙跳台阶问题
  • 后端java——如何为你的网页设置一个验证码
  • Arduino平台软硬件原理及使用——热释电传感器的使用
  • ChatGPT多模态命名实体识别
  • 哈希表,哈希桶及配套习题
  • qml 图片浏览器旋转、按鼠标缩放
  • 引领数字时代:万码优才如何变革IT人才招聘新体验(这里有更精准的推荐)
  • CasaOS香橙派安装HomeAssistant智能家居系统并实现远程管理家中智能设备
  • 【云原生开发】K8S多集群资源管理平台架构设计
  • 第30周:彩色图片分类(Tensorflow实战第二周)
  • Feign调用第三方,想要单独的拦截器,但是变为全局拦截器
  • 基于 RNN 的语言模型
  • 如何提高总线抗扰度之EFT篇
  • python常用的第三方库下载方法
  • 自闭症康复技术研究前沿:探索新突破
  • word及Excel常见功能使用
  • Linux环境离线安装Ollama
  • 诺贝尔物理学奖的新篇章:机器学习与神经网络的光辉时刻
  • WMV怎么转MP4?五个简单好用的视频格式转换方法!
  • channel error 报错【已解决】
  • 告别局域网限制!轻松远程访问本地Paperless-ngx文档管理系统远程办公