英文:
Spring CGLIB, transactions and private final field initialization
问题
我在我的Spring Boot应用程序中有以下的类层次结构:
public abstract class A {
private final ObjectMapper objectMapper = new ObjectMapper();
public void method1(Object object) {
this.objectMapper.writeValueAsString(object);
}
}
@Component
public class B extends A {
public void method2() {
method1();
}
}
在这种情况下,一切都正常工作。
但是当我在method2()
的声明中添加@Transactional(rollbackFor = Exception.class)
注解,就像这样:
public abstract class A {
private final ObjectMapper objectMapper = new ObjectMapper();
public void method1() {
this.objectMapper; // 总是NULL
}
}
@Component
public class B extends A {
@Transactional(rollbackFor = Exception.class)
public void method2() {
method1();
}
}
并且执行method2()
时,由于this.objectMapper
为NULL
,method1()
中会出现NullPointerException
错误;
如何让Spring在添加了@Transactional(rollbackFor = Exception.class)
的情况下,正确地初始化private final ObjectMapper objectMapper
?
此外,使用@Transactional
注解时,this
的类是B$$EnhancerBySpringCGLIB
,而没有注解时则是普通的B
。因此,看起来CGLIB无法正确初始化private final ObjectMapper objectMapper
... 是否有任何解决方法?
英文:
I have the following class hierarchy in my Spring Boot application:
public abstract class A {
private final ObjectMapper objectMapper = new ObjectMapper();
public void method1(Object object) {
this.objectMapper.writeValueAsString(object);
}
}
@Component
public class B extends A {
public void method2() {
method1();
}
}
in such case everything is working fine.
But when I add @Transactional(rollbackFor = Exception.class)
annotation to method2()
declaration, like for example:
public abstract class A {
private final ObjectMapper objectMapper = new ObjectMapper();
public void method1() {
this.objectMapper; // always NULL
}
}
@Component
public class B extends A {
@Transactional(rollbackFor = Exception.class)
public void method2() {
method1();
}
}
and execute method2()
it fails with NullPointerException
in method1()
because of this.objectMapper
is NULL
;
How to let Spring correctly initialize the private final ObjectMapper objectMapper
even in case of @Transactional(rollbackFor = Exception.class)
is added?
Also, in case of @Transactional
annotation the class of this
is B$$EnhancerBySpringCGLIB
and without annotation is just plain B
. So, looks like CGLIB unable to properly initialize private final ObjectMapper objectMapper
.. Is there any workarounds how it can be solved?
答案1
得分: 1
Sure, here's the translated code:
在你的代码中移除 `final` 关键字。你正在使用带有 `CGLIB` 的 `@Transactional`。`CGLIB` 的工作原理是通过扩展你的类来创建代理。由于下面的方法是 final 的,它无法进行扩展,因为 final 类无法被扩展。
@Transactional(rollbackFor = Exception.class)
public void method2() {
method1();
}
英文:
Remove the final
in your code. You are using @Transactional
with CGLIB
. How CGLIB
works is it creates a proxy by extending your class. Since the below method is final it cannot extend it, since final classes cannot be extended.
@Transactional(rollbackFor = Exception.class)
public final void method2() {
method1();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论