2015-03-16 24 views
5

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

Trả lời

2

@EnableAspectJAutoProxy chú thích áp dụng cho @Aspect chú thích, không phải trên @Transactional chú thích. Đối với điều đó, bạn cần có chú thích @EnableTransactionManagement trên @Configuration lớp học, với giá trị thuộc tính proxyTargetClass = true.

@Configuration 
@EnableAspectJAutoProxy(proxyTargetClass = true) 
@EnableTransactionManagement(proxyTargetClass = true) 
public class ApplicationConfiguration { 
    ... 
} 
+0

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

+0

@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'. –

+1

@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'. –

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