简体   繁体   中英

How to implement concrete aspect extending abstract aspect having field with annotations eligible for load time weaving in aspect itself

I am facing a problem while implementing concrete aspect in aspectJ. Below are the related code snippets. I have two abstract aspects - FieldAspect.java and AbstractTracing.java . I am defining concrete aspects in xml - ConcreteTracingimpl and MyFieldAspect and this is not by code. In Main.java , I am calling Test.getTestMethod() and so, before calling this method, as @method is annotated, around advice in AbstractTracing.java gets applied but AbstractTracing.java has also a static field annotated with @field annotation and hence, the field should be initialized with the value andy but it is null.

If an abstract aspect contains fields with annotations and these fields are applicable for load time weaving, how this should be implemented ? Please guide me. Many thanks.

AbstractTracing.java

package main.java.aop.extend;
import main.java.aop.field.Field;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;. 
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public abstract class AbstractTracing {

@Field
static String x;

@Pointcut
public abstract void trace();

@Around("trace()")
public void traceMethod() {
    System.out.println("In trace method of AbstractTracing class : " + x);
 }   

}

FieldAspect.java

package main.java.aop.field;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public abstract class FieldAspect {
@Pointcut
public abstract void getField();

@Around("getField()")
public String getFieldValue() {     
    return "Andy";
 }  
}

aop.xml

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
<aspects>
<concrete-aspect name="main.java.aop.extend.ConcreteTracingimpl"
        extends="main.java.aop.extend.AbstractTracing">
        <pointcut name="trace"
            expression="execution(@main.java.aop.method.Method * * (..))" />
    </concrete-aspect>
<concrete-aspect name="main.java.aop.field.MyFieldAspect"
        extends="main.java.aop.field.FieldAspect">
        <pointcut name="getField" expression="get(@main.java.aop.field.Field * *)" />
    </concrete-aspect>
<weaver options="-verbose -showWeaveInfo" />
</aspectj>

Field.java

package main.java.aop.field;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Field {
}

Method.java

package main.java.aop.field;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Method {
}

Main.java

package main.java.aop.main;

import main.java.aop.extend.Test;

public class Main {

public static void main(String[] args) {

    System.out.println("<---------- EXTENDS example ---------->");
    Test.testMethod();
 }
}

Test.java

package main.java.aop.extend;

import main.java.aop.method.Method;

public class Test {

@Method
public static void testMethod() {
    System.out.println("calling test method in test class");
 }
}

Interesting situation, looks like an AspectJ bug. From what I can see the abstract aspects themselves are not being passed to the weaver for weaving. We can see that if you turn on the additional flag in weaver options (-debug):

[AppClassLoader@58644d46] info AspectJ Weaver Version 1.8.4 built on Thursday Nov 6, 2014 at 20:19:21 GMT
[AppClassLoader@58644d46] info register classloader sun.misc.Launcher$AppClassLoader@58644d46
[AppClassLoader@58644d46] info using configuration /Users/aclement/play/sridhar/META-INF/aop.xml
[AppClassLoader@58644d46] info define aspect main.java.aop.extend.ConcreteTracingimpl
[AppClassLoader@58644d46] info define aspect main.java.aop.field.MyFieldAspect
[AppClassLoader@58644d46] debug weaving 'main.java.aop.extend.ConcreteTracingimpl'
[AppClassLoader@58644d46] debug generating class 'main.java.aop.extend.ConcreteTracingimpl'
[AppClassLoader@58644d46] debug weaving 'main.java.aop.field.MyFieldAspect'
[AppClassLoader@58644d46] debug generating class 'main.java.aop.field.MyFieldAspect'
[AppClassLoader@58644d46] debug weaving 'main.java.aop.main.Main'
[AppClassLoader@58644d46] weaveinfo Join point 'field-get(java.lang.String main.java.aop.extend.AbstractTracing.x)' in Type 'main.java.aop.main.Main' (Main.java:11) advised by around advice from 'main.java.aop.field.MyFieldAspect' (FieldAspect.java:7)
<---------- EXTENDS example ---------->
[AppClassLoader@58644d46] debug weaving 'main.java.aop.extend.Test'
[AppClassLoader@58644d46] weaveinfo Join point 'method-execution(void main.java.aop.extend.Test.testMethod())' in Type 'main.java.aop.extend.Test' (Test.java:8) advised by around advice from 'main.java.aop.extend.ConcreteTracingimpl' (AbstractTracing.java)
[AppClassLoader@58644d46] debug generating class 'main.java.aop.extend.Test$AjcClosure1'
[AppClassLoader@58644d46] debug cannot weave 'org.aspectj.lang.NoAspectBoundException'
In trace method of AbstractTracing class : null

Now why it isn't being passed to the weaver, good question. Possibly it is the re-entrancy guards that are in place to stop the weaver entering itself once already doing something.

However, I've changed things a little and can get it to work, I use a special feature that is hidden in one of the release READMEs. When you have aspects like you have you can actually define the whole aspect in the XML and just use the code to hold the behavior, you don't need any aspect annotations. So if I rewrite your abstract aspects like this:

package main.java.aop.field;

class FieldAspect {
  static String getField() {
    return "Andy";
  }
}

package main.java.aop.extend;

public class AbstractTracing {

  @Field
  public static String x;

  public static void traceMethod() {
    System.out.println("In trace method of AbstractTracing class : " + x);
  }   

}

Then this aop.xml:

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
<aspects>

  <concrete-aspect name="main.java.aop.field.MyFieldAspect">
    <around pointcut="get(@main.java.aop.field.Field * *)" invokeClass="main.java.aop.field.FieldAspect" invokeMethod="getField()"/>
  </concrete-aspect>

  <concrete-aspect name="main.java.aop.extend.ConcreteTracingImpl">
    <around pointcut="execution(@main.java.aop.method.Method * *(..))" invokeClass="main.java.aop.extend.AbstractTracing" invokeMethod="traceMethod()"/>
  </concrete-aspect>

</aspects>
<weaver options="-verbose -showWeaveInfo" />
</aspectj>

(The documentation on this feature is here: http://www.eclipse.org/aspectj/doc/released/README-1612.html )

Now when I run it

[AppClassLoader@58644d46] info AspectJ Weaver Version 1.8.4 built on Thursday Nov 6, 2014 at 20:19:21 GMT
[AppClassLoader@58644d46] info register classloader sun.misc.Launcher$AppClassLoader@58644d46
[AppClassLoader@58644d46] info using configuration /Users/aclement/play/sridhar/META-INF/aop.xml
[AppClassLoader@58644d46] info define aspect main.java.aop.field.MyFieldAspect
[AppClassLoader@58644d46] info define aspect main.java.aop.extend.ConcreteTracingImpl
<---------- EXTENDS example ---------->
[AppClassLoader@58644d46] weaveinfo Join point 'method-execution(void main.java.aop.extend.Test.testMethod())' in Type 'main.java.aop.extend.Test' (Test.java:8) advised by around advice from 'main.java.aop.extend.ConcreteTracingImpl' (no debug info available)
[AppClassLoader@58644d46] weaveinfo Join point 'field-get(java.lang.String main.java.aop.extend.AbstractTracing.x)' in Type 'main.java.aop.extend.AbstractTracing' (AbstractTracing.java:13) advised by around advice from 'main.java.aop.field.MyFieldAspect' (no debug info available)
In trace method of AbstractTracing class : Andy

You can see the join points in the 'abstract aspects' are being woven this time. However, the constraints on the code you point to from the XML (ie that the methods need to be static) - I don't know if that is ok for you or not? The problem you found is definitely a bug (please raise it), I just offer this alternative way of expressing aspects as a workaround.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM