Spring Dependency Внедрение аннотированного аспекта - PullRequest
5 голосов
/ 28 августа 2009

Использование Spring У меня были некоторые проблемы с внедрением зависимостей в аннотированный класс Aspect. CacheService внедряется при запуске контекста Spring, но когда происходит переплетение, он говорит, что cacheService имеет значение null. Поэтому я вынужден вручную просмотреть контекст весны и получить бин оттуда. Есть ли другой способ сделать это?

Вот пример моего Аспекта:

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import com.mzgubin.application.cache.CacheService;

@Aspect
public class CachingAdvice {

  private static Logger log = Logger.getLogger(CachingAdvice.class);

  private CacheService cacheService;

  @Around("execution(public *com.mzgubin.application.callMethod(..)) &&"
            + "args(params)")
    public Object addCachingToCreateXMLFromSite(ProceedingJoinPoint pjp, InterestingParams params) throws Throwable {
    log.debug("Weaving a method call to see if we should return something from the cache or create it from scratch by letting control flow move on");

    Object result = null;
    if (getCacheService().objectExists(params))}{
      result = getCacheService().getObject(params);
    } else {
      result = pjp.proceed(pjp.getArgs());
      getCacheService().storeObject(params, result);
    }
    return result;
  }

  public CacheService getCacheService(){
    return cacheService;
  }

  public void setCacheService(CacheService cacheService){
    this.cacheService = cacheService;
  }
}

Ответы [ 3 ]

4 голосов
/ 31 марта 2010

Поскольку аспект создается перед контейнером Spring, вы должны извлечь аспект из фабричного метода Aspect aspectOf (ExampleClass.class).

Из конфигурации Spring XML вы можете получить аспект (объект) следующим образом:

<bean id="traceAspect" class="aspects.trace.TraceAspect"
    factory-method="aspectOf" />

Фабричные методы - это обычный способ получения объектов, созданных вне контейнера Spring, таких как Enum.

3 голосов
/ 25 сентября 2009

Проблема, насколько я понимаю, в том, что Spring создает для вас bean-компонент этого типа, но среда AspectJ также создает экземпляры этого типа, потому что не знает, что Spring это сделал.

Я полагаю, что вы хотите предоставить Spring фабричный метод, который будет использоваться для создания экземпляра bean-компонента, который также позволяет AspectJ знать, что Aspect создан:

<!-- An @Aspect-annotated class -->
<bean id="bar" class="com.foo.bar" factory-method="aspectOf">
    <property name="meaning" value="42" />
</bean>

Чтобы отдать должное, я столкнулся с этим вопросом ранее сегодня, а затем нашел ответ в другом месте позже, поэтому я возвращаюсь, чтобы замкнуть петлю.

Я не совсем ясен в связи с магией, происходящей здесь, но я вижу, что есть класс Aspect, который предоставляет некоторые статические конструкторы этого аромата. Предположительно, AspectJ также использует статические методы с одинаковыми именами для каждого аспекта, чтобы облегчить этот вид построения.

2 голосов
/ 16 марта 2010

Я тоже сталкивался с такой проблемой.

Вот как это было исправлено:

@Aspect
public class MyAspect {
  @Resource // telling spring that at first look up bean by name;
  Session session; // resource that won't of being setup;

  private static class MyAspectHolder {
    static final MyAspect instance = new MyAspect();
  }

  ...

  // special purpose method w/o it - stuff doesnt work;
  public static MyAspect aspectOf() {
    return MyAspectHolder.instance;
  }
}

И, конечно, не забывайте <aop:aspectj-autoproxy /> в вашей конфигурации вместе с определением аспектного компонента.

...