2017-07-03 5 views
5

私のサービスのメソッドで@Transactional注釈を使用してフィールドを遅延ロードしようとしています。しかし、私の実装クラスの@Transactionalを使用すると、すべての自動フィールドが作成されますnull春のブート2 @トランザクションの注釈によってAutowiredフィールドが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; 
} 

は、事前にありがとう:

は、ここに私の実装です。

+3

メソッドから 'final'を削除するか、' application.properties'で 'spring.aop.proxy-target-class = false'を設定してください。 **注:**これはSpring Boot 1.5.3以上が必要です。 –

+0

Springアプリケーションでトランザクションコンテキストが有効になっていますか? – drgPP

+0

取引をほとんど読んでいる間に役に立たないようにしてください。読書取引が必要ですか? – Zorglube

答えて

5

トランザクションはAOPを使用して適用されますが、SpringのデフォルトのAOPメカニズムはプロキシを使用することです。 Springブートを使用する場合、プロキシモードはクラスベースのプロキシに設定されます。

これは2通りの方法で修正できます。

  1. 、作成するあなたは、これはあなたのUserServiceImplのプロキシにつながる@Transactionalをaded時に今すぐあなたのapplication.properties

spring.aop.proxy-target-class=falseを追加して、メソッドからクラスを

  • 無効にクラスベースのプロキシをfinalを削除しますベースのプロキシは正確です。あなたのUserServiceImpl用にサブクラスが作成され、すべてのメソッドがオーバーライドされてTransactionInterceptorが適用されます。ただし、メソッドがfinalとマークされているため、動的に作成されたクラスはこのメソッドをオーバーライドできません。その結果、メソッドは動的に作成されたプロキシクラスのフィールドインスタンスを調べ、常にnullになります。

    finalを削除すると、メソッドがオーバーライドされ、ビヘイビアが適用され、適切なフィールドインスタンス(プロキシの代わりに実際のUserServiceImpl)が表示されます。

    クラスベースのプロキシを無効にすると、サービスが実装するすべてのインタフェースを実装する基本的に薄いラッパーであるJDK動的プロキシが取得されます。追加された動作(トランザクション)を適用し、実際のサービスを呼び出します。必要な実際のクラスの拡張はありません。そのため、(インターフェイスの一部である限り)最終的なメソッドをプロキシすることができます。

  • 関連する問題