Метод перехвата с Spring AOP с использованием только аннотаций - PullRequest
3 голосов
/ 10 апреля 2010

В моем файле контекста Spring есть что-то вроде этого:

<bean id="userCheck" class="a.b.c.UserExistsCheck"/>
<aop:config>
      <aop:aspect ref="userCheck">
         <aop:pointcut id="checkUser"
                expression="execution(* a.b.c.d.*.*(..)) &amp;&amp; args(a.b.c.d.RequestObject)"/>
         <aop:around pointcut-ref="checkUser" method="checkUser"/>
      </aop:aspect>
</aop:config>    

a.b.c.UserExistsCheck выглядит так:

@Aspect
public class UserExistsCheck {

@Autowired
private UserInformation userInformation;

public Object checkUser(ProceedingJoinPoint pjp) throws Throwable {
    int userId = ... //get it from the RequestObject passed as a parameter
    if (userExists(userId)) {
        return pjp.proceed();
    } else {
        return new ResponseObject("Invalid user);
    }
}

И класс, который перехватывается с этим материалом, выглядит так:

public class Klazz {
    public ResponseObject doSomething(RequestObject request) {...}
}

Это работает. UserExistCheck выполняется по желанию перед передачей вызова в Klazz. Проблема в том, что это единственный способ, с помощью которого я работал. Чтобы заставить это работать, используя аннотации вместо файла контекста, кажется слишком большим для моего маленького мозга. Итак ... как именно я должен аннотировать методы в UserExistsCheck и Klazz? И мне все еще нужно что-то еще? Еще один класс? Все еще что-то в файле контекста?

Ответы [ 3 ]

5 голосов
/ 10 апреля 2010

Включили ли вы АОП на основе аннотаций? документация говорит, что вы должны добавить

<aop:aspectj-autoproxy/>

к вашей конфигурации пружины. Затем вам нужно добавить аннотацию перед вашим checkUser методом. Похоже, вы хотите @Around совет, как описано здесь .

@Aspect
public class UserExistsCheck {

  @Around("execution(* a.b.c.d.*.*(..)) && args(a.b.c.d.RequestObject)")
  public Object checkUser(ProceedingJoinPoint pjp) throws Throwable {
3 голосов
/ 10 апреля 2010

Из приведенного примера кода видно, что вы пытаетесь создать совет для класса, который не реализует никаких интерфейсов. Как описано в разделе Механизмы прокси документации Spring, если вы собираетесь это сделать, вам нужно включить CGLIB:

<aop:aspectj-autoproxy proxy-target-class="true" />

Я лично нашел, что это немного более привередливо, чем указывается в документации, и хотя это работает, если все звезды правильно выровнены, это часто проще - и предпочтительно с точки зрения дизайна - - объявить ваш совет АОП по интерфейсу следующим образом. (Обратите внимание, что вам нужно получить свой экземпляр KlazzImpl от вашего BeanFactory / ApplicationContext.)

public interface Klazz {
  ResponseObject doSomething(RequestObject request);
}

public class KlazzImpl implements Klazz {
  public ResponseObject doSomething(RequestObject request) {...}
}

Кроме того, использование вами выражения args немного запрещено. Смотрите следующее:

@Aspect
public class UserExistsCheck {
  @Autowired
  private UserInformation userInformation;

  @Around("execution(* a.b.c.d.*.*(..)) && args(reqObj)")
  public Object checkUser(ProceedingJoinPoint pjp, a.b.c.d.RequestObject reqObj) throws Throwable {
      // ...
  }
}

Эти изменения должны сделать работу.

1 голос
/ 28 августа 2012

с весны 3.1 добавьте @EnableAspectJAutoProxy(proxyTargetClass=true) к вашему @Configuraiton

...