spring 3.0 AOP Pointcut не хорошо сформирован: ожидание ошибки " шаблон имени
следующее мое объявление pointcut и advise
//PointCut on A method which takes two parameters and is in a DAO
@Pointcut("execution(backend.repository.QuestionsRepository.AnswerQuestion (..))")
public void answerQuestionPointCut() {}
@Around(
value="web.activity.advisors.UserActivityAdvisor.answerQuestionPointCut()",
argNames="question,answer"
)
// Do something
}
Я получаю следующую ошибку
Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: Pointcut is not well-formed: expecting 'name pattern' at character position 65
execution(backend.repository.QuestionsRepository.AnswerQuestion (..))
^
Я застрял на этом, любые указатели
3 ответов
вам не хватает возвращаемого типа:
@Pointcut("execution(* backend.repository.QuestionsRepository.AnswerQuestion (..))")
и вы должны связать имена аргументов, что-то вроде этого:
@Pointcut("execution(* backend.repository.QuestionsRepository.AnswerQuestion (..))
&& args(question, answer)") // wrapped for readability only
Решение
Интерфейс:
package foo.bar.service;
public interface Service{
void whack(String thing, Integer thang);
}
класс реализации:
package foo.bar.service;
public class DefaultService implements Service{
@Override
public void whack(final String thing, final Integer thang){
System.out.println(
"Inside thing: " + thing + ", inside thang: " + thang
);
}
}
Весна AOP аспект:
@Aspect
public class ServiceAspect{
@Pointcut("execution(* foo.bar.service.*.*(..))")
public void serviceMethodExecution(){
}
@Around(value = "serviceMethodExecution() && args(param1, param2)")
public void aroundServiceMethodExecution(final ProceedingJoinPoint pjp,
final String param1,
final Integer param2) throws Throwable{
System.out.println("Before thing: " + param1 + ", before thang: "
+ param2);
pjp.proceed();
System.out.println("After thing: " + param1 + ", after thang: "
+ param2);
}
}
контексте Spring XML-код:
<aop:aspectj-autoproxy proxy-target-class="false" />
<bean class="foo.bar.service.DefaultService" />
<bean class="foo.bar.aspects.ServiceAspect" />
основной класс для тестирование:
теперь вот основной метод для проверки всего процесса. Он запускает Spring ApplicationContext без конфигурации XML с вышеуказанным XML, определяющим компонент службы и аспект (оказывается, что решение без XML работало только потому, что у меня было включено плетение AspectJ, я не знаю, какие бобы я должен включить, чтобы включить aspectj-autoproxy, поэтому я теперь использую ClassPathXmlApplicationContext
С этим минимальный XML):
public static void main(final String[] args){
final ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("classpath:/aspectContext.xml");
final Service service = applicationContext.getBean(Service.class);
service.whack("abc", 123);
}
выход:
Before thing: abc, before thang: 123
Inside thing: abc, inside thang: 123
After thing: abc, after thang: 123
это должно вам начать работу. В принципе: вам нужно проверить, что методы, которые вы перехватываете, поддерживаются интерфейсом службы, если вы используете прокси JDK (spring default). Читайте здесь о Spring AOP прокси механизмы.
Примечание:
как вы видите, я связываю аргументы метода с аспектом, а не pointcut, следовательно, делая pointcut многоразовым для методы с разными сигнатурами аргументов. Но также можно было бы связать их в pointcut, например:
@Pointcut(value = "execution(* foo.bar.service.*.*(..)) && args(a,b)",
argNames = "a,b")
public void serviceMethodExecution(final String a, final Integer b){
}
@Around(value = "serviceMethodExecution(param1, param2)",
argNames = "param1,param2")
public void aroundServiceMethodExecution(final String param1,
final Integer param2,
final ProceedingJoinPoint pjp) throws Throwable{
System.out.println("Before thing: " + param1 + ", before thang: "
+ param2);
pjp.proceed();
System.out.println("After thing: " + param1 + ", after thang: "
+ param2);
}
обратите внимание, что у вас аналогичное поведение с @Before
аннотации org.aspectj.lang.annotation.Before
.
вы можете использовать это выражение без исполнение ключевое слово и без типа возврата:
@Before("allGetters()")
или так:
@Before("execution(public * allGetters())")
но вы не можете использовать execution
ключевое слово без использования возвращаемого типа.
вы должны писать так
@Pointcut("execution(* backend.repository.QuestionsRepository.AnswerQuestion (..))")
обратите внимание "... (* backend..."
*
и следует использовать пробел.