Spring CGLIB,事务和私有final字段初始化

huangapple go评论61阅读模式
英文:

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.objectMapperNULLmethod1()中会出现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();
}

huangapple
  • 本文由 发表于 2020年8月27日 20:02:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63615557.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定