Thực ra tôi đang nhầm lẫn về hành vi của các proxy mùa xuân. Tôi nghĩ rằng tôi biết sự khác biệt chính giữa các cơ chế proxy của j2ee, cglib và aspectj. Tôi đã bật proxy tự động aspectj trong lớp cấu hình và phần tử được bao gồm trong đường dẫn lớp.Proxy AOP mùa xuân không hoạt động như mong đợi
cấu hình của tôi
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ApplicationConfiguration {
...
}
AspectJ phụ thuộc
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.5</version>
</dependency>
Bằng cách sử dụng thiết lập đơn giản này tôi đã giả định rằng việc tiêm đậu như dự định. Nhưng thay vào đó, kết quả ứng dụng của tôi là IllegalArgumentException
s với các thông báo như "Không thể đặt [...] trường [...] thành com.sun.proxy. $ Proxy30". Điều đó có nghĩa là mùa xuân sử dụng proxy j2ee cho dịch vụ của tôi, ngay cả khi đã kích hoạt proxy theo ngữ cảnh.
Cuối cùng tôi đã tìm ra rằng các giao diện trên dịch vụ của tôi gây ra hành vi này. Có vẻ như mùa xuân quyết định sử dụng proxy j2ee khi dịch vụ của tôi thực hiện bất kỳ giao diện nào. Nếu tôi loại bỏ chúng, nó hoạt động.
thất bại:
@Service
@Validated
public class MyService implements Interface1, Interface2 {
@override
public void methodFromInterface1() {
}
@override
public void methodFromInterface2() {
}
public void serviceMethod() {
}
}
OK:
@Service
@Validated
public class MyService {
public void methodFromInterface1() {
}
public void methodFromInterface2() {
}
public void serviceMethod() {
}
}
Cho đến bây giờ tôi đã hiểu rằng giao diện được yêu cầu cho proxy J2EE. Nhưng nó mới đối với tôi, rằng một cglib/aspectj proxy không hoạt động với các bean thực hiện các giao diện.
Có cách nào để ...
... buộc mùa xuân không sử dụng j2ee proxy?
... buộc mùa xuân sử dụng cglib/aspectj proxy (ngay cả đối với các lớp có giao diện)?
Đó có phải là lỗi hoặc hành vi mong muốn của mùa xuân không?
Sửa: Ví dụ cập nhật, @Transational
thay thế bằng @Validated
Edit2: Giải pháp:@Validated
bị ảnh hưởng bởi MethodValidationPostProcessor
. Vì vậy, tài sản proxyTargetClass
phải được đặt thành true
cho hạt này.
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
final MethodValidationPostProcessor methodValidationPostProcessor;
methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setProxyTargetClass(true);
return methodValidationPostProcessor;
}
Bạn nói đúng. Tôi cũng có
@EnableTransactionManagement
được định cấu hình trên lớp cấu hình thứ hai, nhưng không cóproxyTargetClass = true
và vì một số lý do nó hoạt động. Xin lưu ý đây chỉ là một ví dụ và vấn đề có thể tái sản xuất với@Validated
trên lớp dịch vụ. – baymon@baymon Chính xác. Vì vậy, bạn đã đặt 'proxyTargetClass = true' thành chú thích đó, để có mùa xuân sử dụng proxy CGLib cho các lớp chú thích' @ Transactional'. –
@baymon Trong thực tế, nếu bạn không sử dụng Spring AOP, bạn thậm chí không cần chú thích '@ EnableAspectJAutoProxy'. Để kích hoạt proxy trên giao diện, bạn có thể sử dụng thuộc tính 'mode' của chú thích' @ EnableTransactionManagement'. –