2012-02-10 25 views
5

Tôi đang viết giản đồ dựa trên rất cơ bản Spring AOP, đây là .xmlTại sao điểm dừng AOP mùa xuân này không được kích hoạt?

<bean id="aoplistener" class="tao.zhang.Listener"/> 

<aop:config> 
    <aop:aspect ref="aoplistener">     
    <aop:pointcut id="whenCalled" expression="execution(* callme(..))" /> 
    <aop:after method="scream" pointcut-ref="whenCalled" /> 
    </aop:aspect> 
</aop:config> 

Phương pháp tiếng hét() trong tao.zhang.Listener chỉ in ra một số văn bản, và được coi là thực hiện bất cứ khi nào một phương thức callme() được gọi.

Tôi có một bean gọi logger trong đó có các phương pháp đăng nhập() và callme()

public void log(){ 
    callme(); 
    System.out.println("Hello from logger ~~~~~~~~~~~~~~~~~~~"); 
} 

public void callme(){ 
    System.out.println("I'm called"); 
} 

Lưu ý rằng callme() được gọi bởi log()

Bây giờ tôi có một scheduler trong đó kêu gọi log() mỗi 5 giây:

<task:scheduler id="myScheduler" pool-size="10"/> 

<task:scheduled-tasks scheduler="myScheduler"> 
    <task:scheduled ref="logger" method="log" fixed-rate="5000"/> 
</task:scheduled-tasks> 

Kỳ lạ thay, tiếng hét() không được gọi, nhưng nếu callme() được gọi trực tiếp:

<task:scheduler id="myScheduler" pool-size="10"/> 

<task:scheduled-tasks scheduler="myScheduler"> 
    <task:scheduled ref="logger" method="callme" fixed-rate="5000"/> 
</task:scheduled-tasks> 

tiếng hét() được gọi!

Mọi đề xuất? Dường như với tôi rằng đường cắt này không khớp với các phương pháp được gọi bên trong một phương pháp khác ...

Trả lời

9

Spring AOP chỉ bẫy một cuộc gọi phương thức khi cuộc gọi được thực hiện thông qua một tay cầm đậu (vì bộ chặn được áp dụng thông qua việc sử dụng đối tượng proxy) và không phải khi phương thức được gọi trực tiếp.

Để làm cho mã của bạn hoạt động, bạn cần chuyển sang sử dụng AspectJ (hoạt động bằng cách viết lại bytecode của lớp, cho phép nó chặn nhiều thứ hơn và làm rõ hơn) hoặc thay đổi cách bạn gọi callme() rằng nó là thông qua một xử lý đậu:

SomeClass selfRef; 

public void log(){ 
    selfRef.callme(); 
    System.out.println("Hello from logger ~~~~~~~~~~~~~~~~~~~"); 
} 

public void callme(){ 
    System.out.println("I'm called"); 
} 

Bạn cần định cấu hình trường selfRef một cách rõ ràng; nó sẽ không tự động.

+0

Vâng, cảm ơn rất nhiều! Tôi chỉ nhai câu này từ cuốn sách hướng dẫn mùa xuân: 'Spring AOP chỉ hỗ trợ thực hiện phương thức tham gia điểm cho Spring bean' – Tao

+1

Tôi thấy rằng nó đã giúp tôi rất nhiều để biết làm thế nào mùa xuân làm việc. Nếu nó làm bất cứ điều gì ưa thích (bao gồm cả AOP) nó cung cấp cho bạn một đối tượng proxy có chứa các điểm chặn nó đòi hỏi. Đối tượng proxy đó - trình xử lý bean, nếu bạn muốn - là cách bạn được yêu cầu thực hiện các cuộc gọi _all_ trên bean, và bạn không nên đi sau lưng của Spring bằng cách gọi thông qua 'this' (đó là cái gọi là 'callme thô() 'does;' this.' là ngầm định). –

+0

Tôi bây giờ cảm thấy rằng mùa xuân AOP là hầu như không hữu ích trong nhiều trường hợp. Trong dự án hiện tại của tôi, tôi muốn lấy một số bản ghi bất cứ khi nào 'callme()' được gọi, và 'callme()' được sử dụng bởi các phương thức khác nhau trong lớp này như là một thường trình con, đó là một tình huống rất phổ biến. – Tao

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