Spring Boot 2@Transaction批注使自动连接的字段为空 [英] Spring boot 2 @Transactional annotation makes Autowired fields null

查看:0
本文介绍了Spring Boot 2@Transaction批注使自动连接的字段为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试在我的服务的方法中使用@Transactional注释来延迟加载域。但是,在我的实现类上使用@Transactional会使所有自动绑定的字段null

以下是我的实现:

@Service
public class UserServiceImpl implements UserService {

 /**
  * DefaultMapper.
  */
 @Autowired
 private DefaultMapper defaultMapper;

 /**
  * Resource service injection.
  */
 @Autowired
 private ResourceService resourceService;

 /**
  * UserRepository.
  */
 @Autowired
 private UserRepository userRepository;

 /**
  * Jwt Factory.
  */
 @Autowired
 private JwtService jwtService;

 @Override
 @Transactional
 public final UserDto findByLogin(final String login) throws ResourceNotFoundException {
 // user repository is null here when using @Transactional
  User user = this.userRepository.findByLogin(login)
   .orElseThrow(() -> new ResourceNotFoundException(
    resourceService.getMessage(MessageBundle.EXCEPTION, "resource.notfound.user.login")
   ));
  UserDto userDto = defaultMapper.asUserDtoWithRoles(user);
  return userDto;
 }

提前谢谢您。

推荐答案

事务是使用AOP应用的,Spring中的默认AOP机制是使用代理。使用Spring Boot时,代理模式设置为基于类的代理。

您可以使用以下两种方法中的一种来解决此问题。

  1. 从您的方法中删除final
  2. 通过将spring.aop.proxy-target-class=false添加到application.properties
  3. 来禁用基于类的代理
现在,当您加载@Transactional时,这将导致您的UserServiceImpl的代理被创建,准确地说是基于类的代理。发生的情况是为UserServiceImpl创建了一个子类,并且所有方法都被覆盖以应用TransactionInterceptor。但是,由于您的方法被标记为final,所以动态创建的类不能覆盖此方法。因此,该方法查看动态创建的代理类中的字段实例,该实例始终为null

当删除final方法时,可以重写该方法,应用该行为,并且它将查看正确的字段实例(实际UserServiceImpl而不是代理)。

禁用基于类的代理时,您将获得一个JDK动态代理,它基本上是一个实现服务实现的所有接口的瘦包装。它应用添加的行为(事务)并调用实际服务。不需要对实际类进行扩展,因此您可以代理最终方法(只要它是您的接口的一部分)。

这篇关于Spring Boot 2@Transaction批注使自动连接的字段为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆