【问题标题】:Spring CGLIB, transactions and private final field initializationSpring CGLIB,事务和私有最终字段初始化
【发布时间】:2020-08-28 03:03:12
【问题描述】:

我的 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; // always NULL
    }

}

@Component
public class B extends A {

    @Transactional(rollbackFor = Exception.class)
    public void method2() {
        method1();
    }

}

并执行method2(),它在method1() 中以NullPointerException 失败,因为this.objectMapperNULL

即使添加了@Transactional(rollbackFor = Exception.class),如何让Spring正确初始化private final ObjectMapper objectMapper

此外,在@Transactional 注释的情况下,this 的类是B$$EnhancerBySpringCGLIB,而没有注释只是普通的B。所以,看起来 CGLIB 无法正确初始化 private final ObjectMapper objectMapper.. 有什么解决方法可以解决吗?

【问题讨论】:

标签: java spring spring-boot spring-data-jpa cglib


【解决方案1】:

删除代码中的final。您正在使用 @TransactionalCGLIBCGLIB 的工作原理是通过扩展您的类来创建代理。由于下面的方法是 final 它不能扩展它,因为 final 类不能扩展。

@Transactional(rollbackFor = Exception.class)

public final void method2() {
    method1();
}

【讨论】:

  • 感谢您的回答!是否可以使用反射 api 或类似的东西?因为我的示例中提到的代码是 3rdparty 库的一部分。
  • 我认为你可以使用 ReflectionUtils.setField("objectmapper",this.getClass().getSuperclass(), new ObjectMapper());
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多