繁体   English   中英

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

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

我正在使用AspectJ在类级别和方法级别实现注释驱动程序方面,以在基于Spring代理的AOP的Spring应用程序中使用。

AnnotationTimeoutAspect公开给Spring应用程序并使用

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

引发以下错误。

解析切点时必需的参数名称不可用

当方面和切入点在单个类(没有Abstract和Concrete类)中实现时,它将按预期工作。

当使用JUnit测试类和Load-Time-Weaving在本地进行测试时,抽象类和混凝土类的分离也可以正常工作。 与基于Spring Proxy的AOP场景一起使用时,这是行不通的。

我的目标是将实现保留在Abstract方面,将切入点保留在Concrete方面,以便我可以根据切入点的需求实现多个Concrete方面。

如果您有任何解决方法,请告诉我。

具体方面

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

抽象方面

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

错误

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

您不能在抽象类中使用@Pointcut。 使用所有切入点创建另一个类,并使其扩展该类。 这些建议可以保留在这里。

暂无
暂无

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

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