почему этот SpringPoint AOP pointcut не срабатывает? - PullRequest
6 голосов
/ 10 февраля 2012

Я пишу очень простую основанную на схеме Spring AOP, вот .xml

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

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

У меня есть компонент с именем logger , в котором есть методы log () и callme ()

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

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

Обратите внимание, что callme () вызывается log ()

Теперь у меня есть планировщик, который вызывает log () каждые 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>

Как ни странно, scream () не вызывается, но если 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>

scream () вызывается!

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

1 Ответ

10 голосов
/ 10 февраля 2012

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; не будет автоматически подключенным.

...