强制 Spring 在运行时使用特定的 class 代替另一个
Force Spring to use a specific class in place of another one at runtime
我的 Spring 应用程序依赖于我需要覆盖 class 的库,比方说 com.dep.A
。我想创建扩展 A
的 class B
,并告诉 spring 每次尝试加载 A
(通过任何代码或依赖项)我想改为加载 B
。
是否有 spring 设置可以实现此目的?如果没有,AspectJ 会是一个选项吗(我认为 Spring 具有 AspectJ 功能)?
编辑:关于用例更具体一点
如果我只能将自己插入 class A
的特定方法的执行流程中,我会非常高兴。事实上,忘记 B
扩展 A
:我真正想要实现的是拦截方法 A.originalMethod(MyObject o)
的执行,并在我的自定义方法中使用 o
B.interceptOriginalMethod()
.
使用 @Autowired
和 @Qualifier
按名称而不是类型加载 bean。下面是例子
@Autowired
@Qualifier("b")
private A a;
以上代码将加载 class B 的引用,前提是 B 也是一个 spring bean。
由于class来自不同的库,听起来不像是spring bean,那么Spring也帮不了你。它基本上归结为对象的构造方式,如果 new 运算符不是您调用的,但是库中的代码您只有两个选择(除非 Jar 已签名,然后我认为没有选择)。
- 加载时间编织。这允许您插入一个切割点并替换方法的代码。这需要使用 java 代理启动 JVM,这应该是最后的手段。
- 如果你有源代码,你可以使用 class 隐藏。您只需将 class 源代码复制到您的源代码树中(相同的包名称)。这是有效的,因为 /classes 几乎总是在 class 路径中的库之前,所以当 classloader 尝试加载 class 它将找到您的修改版本,因此隐藏了原始版本。
我曾多次使用选项 2 来修复不同开源库中的小问题,当时我懒得从源代码重建整个库。升级库时必须小心,以防他们更改了底层代码。
尽管@Klaus Groenbaek 的回答是正确的(我会这样标记),但我已经使用另一种方法解决了我的问题。
我很幸运 com.dep.A
被注释为 Spring 的 @ConditionalOnMissingBean
。
因此,只需创建 bean B
extending A
并在您的主应用程序中 class 声明:
@Bean
public A a(){
return new A();
}
Spring 将加载您的 class 而不是原始的。
我的 Spring 应用程序依赖于我需要覆盖 class 的库,比方说 com.dep.A
。我想创建扩展 A
的 class B
,并告诉 spring 每次尝试加载 A
(通过任何代码或依赖项)我想改为加载 B
。
是否有 spring 设置可以实现此目的?如果没有,AspectJ 会是一个选项吗(我认为 Spring 具有 AspectJ 功能)?
编辑:关于用例更具体一点
如果我只能将自己插入 class A
的特定方法的执行流程中,我会非常高兴。事实上,忘记 B
扩展 A
:我真正想要实现的是拦截方法 A.originalMethod(MyObject o)
的执行,并在我的自定义方法中使用 o
B.interceptOriginalMethod()
.
使用 @Autowired
和 @Qualifier
按名称而不是类型加载 bean。下面是例子
@Autowired
@Qualifier("b")
private A a;
以上代码将加载 class B 的引用,前提是 B 也是一个 spring bean。
由于class来自不同的库,听起来不像是spring bean,那么Spring也帮不了你。它基本上归结为对象的构造方式,如果 new 运算符不是您调用的,但是库中的代码您只有两个选择(除非 Jar 已签名,然后我认为没有选择)。
- 加载时间编织。这允许您插入一个切割点并替换方法的代码。这需要使用 java 代理启动 JVM,这应该是最后的手段。
- 如果你有源代码,你可以使用 class 隐藏。您只需将 class 源代码复制到您的源代码树中(相同的包名称)。这是有效的,因为 /classes 几乎总是在 class 路径中的库之前,所以当 classloader 尝试加载 class 它将找到您的修改版本,因此隐藏了原始版本。
我曾多次使用选项 2 来修复不同开源库中的小问题,当时我懒得从源代码重建整个库。升级库时必须小心,以防他们更改了底层代码。
尽管@Klaus Groenbaek 的回答是正确的(我会这样标记),但我已经使用另一种方法解决了我的问题。
我很幸运 com.dep.A
被注释为 Spring 的 @ConditionalOnMissingBean
。
因此,只需创建 bean B
extending A
并在您的主应用程序中 class 声明:
@Bean
public A a(){
return new A();
}
Spring 将加载您的 class 而不是原始的。