tags:

views:

723

answers:

1

I have created two Spring AOP pointcuts that are completely separate and will be woven in for different parts of the system. The pointcuts are used in two different around advices, these around-advices will point to the same Java method. How the xml-file looks:

<aop:config>
    <aop:pointcut expression="execution(......)" id="pointcutOne" />
    <aop:pointcut expression="execution(.....)" id="pointcurTwo" />

<aop:aspect id="..." ref="springBean">
    <aop:around pointcut-ref="pointcutOne" method="commonMethod" />
    <aop:around pointcut-ref="pointcutTwo" method="commonMethod" />
</aop:aspect>
</aop:config>

The problem is that only the last pointcut works (if I change the order "pointcutOne" works because it is last). I have gotten it to work by creating one big pointcut, but I would like to have them separate. Any suggestions to why only one of the pointcuts works at a time?

+2  A: 

Try to have the pointcut and advice inside the <aop_aspect> element. Something like this:

<aop:config>
  <aop:aspect id="aspect1" ref="springBean">
    <aop:pointcut expression="execution(......)" id="pointcutOne" />
     <aop:around pointcut-ref="pointcutOne" method="commonMethod" />
  </aop:aspect>

  <aop:aspect id="aspect2" ref="springBean">
    <aop:pointcut expression="execution(.....)" id="pointcurTwo" />
    <aop:around pointcut-ref="pointcutTwo" method="commonMethod" />
  </aop:aspect>
</aop:config>

I guess your XML configuration resulted in just one proxy object, while it should have been two proxy objects.


Btw: You should consider using @AspectJ syntax instead. It's just Java with pointcuts and advices in annotations. It works well with Spring AOP and offers more functionality than the XML alternative.

All you need in your configuration to enable @AspectJ aspects with Spring AOP:

<aop:aspectj-autoproxy>
     <aop:include name="aspect1" />
     <aop:include name="aspect2" />
</aop:aspectj-autoproxy>

<bean id="aspect1" class="com.demo.Aspect1"/>
<bean id="aspect2" class="com.demo.Aspect2"/>

And the Aspect could be something like this:

@Aspect
public class Aspect1 {

    @Pointcut("execution(* *(..))")
    public void demoPointcut() {}

    @Around("demoPointcut()")
    public void demoAdvice(JoinPoint joinPoint) {}
}

Updated:

Example that uses a pointcut to combine three other pointcuts:

@Pointcut("traceMethodsInDemoPackage() && notInTestClass() " +
    "&& notSetMethodsInTraceDemoPackage()")
public void filteredTraceMethodsInDemoPackage() {}
Espen
Same problem, this is very strange.It does work just fine when I have only one pointcut, but it quickly becomes very large.Thanks for the suggestions about using annotations. I totally agree with you that it is a better solution than using xml. I do have similar pointcuts as annotations in addition to the xml, but I wanted to support xml as well because it will make it possible for the main project to change the aspects without recompiling.
Jarle Hansen
That's odd. The proxy objects should have been called recursively before and after the method adviced by your joinpoint. If it works with one pointcut, you can create a third pointcut that combines the first two and use this in the around advice.
Espen
Using the annotations works great, so I think Ill update at least most of the aspects to use this instead of xml. Just have to be aware that we need to recompile to make changes.Thanks for the help!
Jarle Hansen