简体   繁体   English

使用@AspectJ语法实现为抽象类和具体类的方面不适用于Spring AOP

[英]Aspects implemented as abstract and concrete classes using @AspectJ syntax not working with Spring AOP

I am implementing annotation driver aspects at class level and method level using AspectJ to be used in Spring applications using Spring proxy based AOP. 我正在使用AspectJ在类级别和方法级别实现注释驱动程序方面,以在基于Spring代理的AOP的Spring应用程序中使用。

When AnnotationTimeoutAspect is exposed to Spring Application and using AnnotationTimeoutAspect公开给Spring应用程序并使用

For Grails applications, set in Config.groovy grails.spring.bean.packages = ['com.xyz.aspect'] or For spring applications <context:component-scan base-package="com.xyz.aspect"/> <aop:aspectj-autoproxy/> 对于Grails应用程序,在Config.groovy grails.spring.bean.packages = ['com.xyz.aspect'] 或者对于Spring应用程序 <context:component-scan base-package="com.xyz.aspect"/> <aop:aspectj-autoproxy/>

Following error is thrown. 引发以下错误。

Required parameter names not available when parsing point cut 解析切点时必需的参数名称不可用

When the aspect and pointcuts are implemented in single class (no Abstract and Concrete classes) it works as expected. 当方面和切入点在单个类(没有Abstract和Concrete类)中实现时,它将按预期工作。

Abstract and Concrete class separation also works fine when testing locally with JUnit test classes and Load-Time-Weaving. 当使用JUnit测试类和Load-Time-Weaving在本地进行测试时,抽象类和混凝土类的分离也可以正常工作。 The same doesn't work when using with Spring Proxy based AOP scenario. 与基于Spring Proxy的AOP场景一起使用时,这是行不通的。

My goal is to keep the implementation in Abstract aspect and pointcuts in Concrete aspect so that I can implement multiple Concrete aspects based in my pointcuts needs. 我的目标是将实现保留在Abstract方面,将切入点保留在Concrete方面,以便我可以根据切入点的需求实现多个Concrete方面。

Please let me know if you have any workaround. 如果您有任何解决方法,请告诉我。

Concrete Aspect 具体方面

@Component
@Order(116)
@Aspect
public class AnnotationTimeoutAspect extends AbstractTimeoutAspect {

    @Pointcut("execution(@com.xyz.annotation.Timeout * *(..)) && @annotation(timeoutConfig)")
    public void executionOfTimeoutMethod(Timeout timeoutConfig) {}

    @Pointcut("execution(public * ((@com.xyz.annotation.Timeout *)+).*(..)) " +
            "&& within(@com.xyz.annotation.Timeout *) && @target(timeoutConfig) " +
            "&& !com.xyz.aspect.SystemArchitecture.groovyMOPMethods()")
    public void executionOfAnyPublicMethodInAtTimeoutType(Timeout timeoutConfig) {}

    @Pointcut("(executionOfTimeoutMethod(timeoutConfig) || executionOfAnyPublicMethodInAtTimeoutType(timeoutConfig))")
    public void timeoutMethodExecution(Timeout timeoutConfig) { }

    @DeclareError("execution(@com.xyz.annotation.Timeout  * *(..) throws !java.util.concurrent.TimeoutException)")
    static final String anError = "Only methods that are declared with throws TimeoutException may have an @Timeout annotation";
}

Abstract Aspect 抽象方面

@Aspect
public abstract class AbstractTimeoutAspect {
    protected final Logger log = LoggerFactory.getLogger(getClass());
    private static class TimeoutThread extends Thread {
        private boolean completed = false;
        private ProceedingJoinPoint point;
        private Throwable throwable;
        private Object value;

        public ProceedingJoinPoint getPoint() {
            return point;
        }

        public Throwable getThrowable() {
            return throwable;
        }

        public Object getValue() {
            return value;
        }

        public boolean isCompleted() {
            return completed;
        }

        public void run() {
            try {
                setValue(point.proceed());
            } catch (Throwable t) {
                setThrowable(t);
            } finally {
                setCompleted(true);
            }
        }

        public void setCompleted(boolean completed) {
            this.completed = completed;
        }

        public void setPoint(ProceedingJoinPoint point) {
            this.point = point;
        }

        public void setThrowable(Throwable throwable) {
            this.throwable = throwable;
        }

        public void setValue(Object value) {
            this.value = value;
        }

    }

    @Around("executionOfAnyPublicMethodInAtTimeoutType(timeoutConfig)")
    public Object timeoutOnClassLevel(final ProceedingJoinPoint point,Timeout timeoutConfig) throws Throwable {
        return  doTimeout(point,timeoutConfig);
    }

    @Around("executionOfTimeoutMethod(timeoutConfig)")
    public Object timeoutOnMethodLevel(final ProceedingJoinPoint point,Timeout timeoutConfig) throws Throwable {
        return  doTimeout(point,timeoutConfig);
    }

    // @Around("timeoutMethodExecution(timeoutConfig)")
    public Object doTimeout(final ProceedingJoinPoint point,Timeout2 timeoutConfig) throws Throwable {
        log.debug(point + " -> " + timeoutConfig);
        Method method = ((MethodSignature) point.getSignature()).getMethod();

        TimeoutThread thread = new TimeoutThread();
        thread.setDaemon(timeoutConfig.daemon());
        thread.setPoint(point);
        thread.start();
        thread.join(timeoutConfig.value());

        if (!thread.isCompleted()) {
            throw new TimeoutException("Method " + method + " exceeded timeout of " + timeoutConfig.value() + " milliseconds");
        } else if (thread.getThrowable() != null) {
            throw thread.getThrowable();
        } else {
            return thread.getValue();
        }
    }

    @Pointcut
    public abstract void executionOfAnyPublicMethodInAtTimeoutType(Timeout timeoutConfig);

    @Pointcut
    public abstract void executionOfTimeoutMethod(Timeout timeoutConfig);

    @Pointcut
    public abstract void timeoutMethodExecution(Timeout timeoutConfig);
}

Error 错误

2014-03-23 16:48:01,924 [localhost-startStop-1] DEBUG annotation.ReflectiveAspectJAdvisorFactory  - Found AspectJ method: public java.lang.Object com.xyz.aspect.AbstractTimeoutAspect.timeoutOnClassLevel(org.aspectj.lang.ProceedingJoinPoint,com.xyz.annotation.Timeout) throws java.lang.Throwable
2014-03-23 16:48:01,925 [localhost-startStop-1] DEBUG annotation.ReflectiveAspectJAdvisorFactory  - Found AspectJ method: public java.lang.Object com.xyz.aspect.AbstractTimeoutAspect.timeoutOnMethodLevel(org.aspectj.lang.ProceedingJoinPoint,com.xyz.annotation.Timeout) throws java.lang.Throwable

Caused by IllegalStateException: Required parameter names not available when parsing pointcut executionOfTimeoutMethod in type com.xyz.aspect.AbstractTimeoutAspect
->>  290 | getDeclaredPointcuts in org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    800 | getDeclaredPointcuts in org.aspectj.weaver.ReferenceType
|    243 | get . . . in org.aspectj.weaver.ResolvedType$PointcutGetter

You cannot have a @Pointcut in an abstract class. 您不能在抽象类中使用@Pointcut。 Make another class with all the pointcuts and make it extend this class. 使用所有切入点创建另一个类,并使其扩展该类。 The advices can remain here. 这些建议可以保留在这里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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