Spring引导2 @Transactional注释使Autowired字段为空

Moh*_*med 5 java spring transactional autowired spring-boot

我试图@Transactional在我的服务的方法中使用注释来懒洋洋地加载一个字段.但是,@Transactional在我的Implementation类上使用会生成所有自动装配的字段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;
 }
Run Code Online (Sandbox Code Playgroud)

先感谢您.

M. *_*num 8

除其他外,事务是使用AOP应用的,Spring中的默认AOP机制是使用代理.使用Spring Boot时,代理模式设置基于类的代理.

您可以通过2种方式之一解决此问题.

  1. final从您的方法中删除
  2. 通过添加spring.aop.proxy-target-class=false到您的.禁用基于类的代理application.properties

现在,当你获得@Transactional这个将导致你的UserServiceImpl创建代理时,确切地说是一个基于类的代理.会发生什么是为您创建子类,UserServiceImpl并且所有方法都被覆盖以应用TransactionInterceptor.但是,当您的方法被标记时final,动态创建的类不能覆盖此方法.因此,该方法查看动态创建的代理类中的字段实例,它始终是null.

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

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