2012-02-10 2 views
5

Я пишу очень простую схему на основе Spring AOP, вот .xmlПочему эта точка привязки Spring AOP не срабатывает?

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

Метод крика() в tao.zhang.Listener просто выводит текст, и должен быть выполняется всякий раз, когда вызывается метод callme().

У меня есть компонент под названием регистратор, который имеет методы входа() и CallME()

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

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

Заметьте, что CallME() вызывается лога()

Теперь у меня есть планировщик, который вызывает журнал() каждые 5 секунд:

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

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

Как ни странно, крика() не вызывается, но если CallME() вызывается непосредственно:

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

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

крика() вызывается!

Любые предложения? Мне кажется, что этот pointcut не соответствует методам, называемым внутри другого метода ...

ответ

9

Spring AOP только ловушки вызова метода, когда вызов выполняется через дескриптор компонента (поскольку перехватчик применяется с использованием прокси-объект), а не когда метод вызывается напрямую.

Для того, чтобы ваш код работал, вам нужно либо переключиться на использование AspectJ (который работает, переписывая байт-код класса, что позволяет ему перехватывать гораздо больше вещей и делать это более прозрачно) или изменить способ, которым вы вызываете callme(), так что что с помощью рожкового ручки:

SomeClass selfRef; 

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

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

Вам нужно настроить selfRef поле явно; это не будет быть автопокрытым.

+0

Да, спасибо большое! Я просто пережевывал это предложение из весенней справочной книги: «Spring AOP поддерживает только точки соединения метода для весенних бобов» – Tao

+1

Я обнаружил, что это помогло мне много узнать, как работает Spring. Если он делает что-нибудь интересное (в том числе AOP), он дает вам прокси-объект, который содержит точки перехвата, которые он требует. Этот прокси-объект - обработчик bean-компонента, если хотите, - это то, как вы должны делать _all_-вызовы в bean-компоненте, и вы не должны идти за спиной Spring, вызывая через 'this' (что является сырой' callme() 'does,' this.' неявно). –

+0

Теперь я чувствую, что Spring AOP вряд ли полезен во многих случаях. В моем текущем проекте я хочу взять некоторый журнал всякий раз, когда вызывается 'callme()', а 'callme()' используется различными методами в этом классе в качестве подпрограммы, что является очень распространенной ситуацией. – Tao

Смежные вопросы