Spring Dependency Injecting an annotated Aspect

雨燕双飞 提交于 2019-11-27 18:56:29

问题


Using Spring I've had some issues with doing a dependency injection on an annotated Aspect class. CacheService is injected upon the Spring context's startup, but when the weaving takes place, it says that the cacheService is null. So I am forced to relook up the spring context manually and get the bean from there. Is there another way of going about it?

Here is an example of my Aspect:

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

回答1:


Since the aspect is created before the Spring container, you have to retrieve the aspect from the Aspect's factory method aspectOf(ExampleClass.class).

From the Spring XML configuration, you can retrieve the aspect (object) like this:

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

Factory methods are the normal way to retrieve objects created outside the Spring container like an Enum.




回答2:


The problem, as I understand it, is that Spring is creating a bean of this type for you, but the AspectJ framework is also creating an instantiation of this type because it doesn't know Spring has done so.

I believe you want to give Spring a factory-method to use to instantiate the bean that also lets AspectJ know the Aspect is created:

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

To give due credit, I came across this question earlier today and then found an answer elsewhere later, so I'm coming back to close the loop.

I'm not crystal clear on the magic happening here, but I do see that there is an Aspects class that provides some static constructors of this flavor. Presumably AspectJ is weaving static methods of the same name onto each Aspect as well to facilitate this kind of construction.




回答3:


I also faced with such problem.

This is how it was fixed:

@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;
  }
}

And of course dont forget <aop:aspectj-autoproxy /> in your config along with aspect bean definition.



来源:https://stackoverflow.com/questions/1343952/spring-dependency-injecting-an-annotated-aspect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!