2017-07-03 17 views
5

Tôi đang cố sử dụng chú thích @Transactional trong một phương pháp trên dịch vụ của tôi để tải một trường một cách lười biếng. Tuy nhiên, sử dụng @Transactional trên lớp Triển khai của tôi làm cho tất cả các trường tự động là null.Khởi động mùa xuân 2 Chú thích @Transactional làm cho các trường Autowired rỗng

Đây là triển khai thực hiện của tôi:

@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; 
} 

Cảm ơn bạn trước.

+3

Xóa 'final' khỏi phương thức của bạn hoặc đặt' spring.aop.proxy-target-class = false' trong 'application.properties' của bạn. ** LƯU Ý: ** Điều này yêu cầu khởi động Spring 1.5.3 hoặc hoạt động đầy đủ! –

+0

Ngữ cảnh giao dịch có được bật trong ứng dụng mùa xuân của bạn không? – drgPP

+0

Thực hiện một giao dịch là phần lớn thời gian vô dụng trong một hành động đọc, bạn có chắc là bạn cần một giao dịch đọc không? – Zorglube

Trả lời

5

Giao dịch, trong số những người khác, được áp dụng bằng AOP, cơ chế AOP mặc định trong Mùa xuân là sử dụng proxy. Khi sử dụng Spring Boot, chế độ proxy được thiết lập proxy dựa trên lớp.

Bạn có thể sửa lỗi này theo 1 trong 2 cách.

  1. Di final từ phương pháp của bạn
  2. Disable proxy dựa lớp bằng cách thêm spring.aop.proxy-target-class=false để bạn application.properties

Bây giờ khi bạn aded @Transactional này sẽ dẫn đến một proxy của UserServiceImpl của bạn được tạo ra, một lớp proxy dựa trên chính xác. Điều gì xảy ra là lớp con được tạo cho UserServiceImpl của bạn và tất cả các phương pháp đều được ghi đè để áp dụng TransactionInterceptor. Tuy nhiên, vì phương thức của bạn được đánh dấu là final lớp được tạo động không thể ghi đè phương thức này. Kết quả là phương thức xem xét các cá thể hiện trường trong lớp proxy được tạo động mà luôn luôn là null.

Khi xóa final phương pháp có thể bị ghi đè, hành vi được áp dụng và nó sẽ xem xét trường hợp trường thích hợp (thực tế là UserServiceImpl thay vì proxy).

Khi vô hiệu hoá proxy dựa trên lớp, bạn sẽ nhận được một JDK Dynamic Proxy mà về cơ bản là một trình bao bọc mỏng thực hiện tất cả các giao diện mà dịch vụ của bạn triển khai. Nó áp dụng hành vi bổ sung (giao dịch) và gọi dịch vụ thực tế. Không có phần mở rộng của lớp thực tế cần thiết và như vậy bạn có thể proxy các phương thức cuối cùng (miễn là nó là một phần của giao diện của bạn).

Các vấn đề liên quan