【问题标题】:Spring Boot AOP unable to get annotation parametersSpring Boot AOP 无法获取注解参数
【发布时间】:2020-02-09 19:08:39
【问题描述】:

使用 Spring Boot v2.2.4。

对于我的自定义 AOP 注释,我想获取赋予被注释方法的注释的值。但我做不到。

我想要做的是应用一些安全注释,它将根据方法允许的限制和访问用户拥有的权限来限制用户对方法的访问。我认为 AOP 是我最好的。

此外,由于我预计这种方法会大量使用,因此我不希望使用基于反射的解决方案。我知道我们可以从连接点获取方法签名并从那里访问注释值。但我听说在生产环境中强烈反对基于反射的解决方案。

注释

package com.example.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
    public String permissions() default "";
}

方面

package com.example.demo;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Aspect
@Component(value = "aspectO")
public class AspectO {
    @Pointcut("execution(public * *(..))")
    public void anyPublic(){}

    @Pointcut("@annotation(com.example.demo.MyAnno)")
    public void myAnnotation(){}

    @Before("myAnnotation()")
    public void reactNow(JoinPoint jp, MyAnno myAnno) {
        System.out.println("allowed permissions are: "+myAnno.permission);
    }
}

主类

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ApplicationContext appCon = SpringApplication.run(DemoApplication.class, args);
        InnerDemoApplication obj = appCon.getBean(InnerDemoApplication.class);
        System.out.println("Howdy");
        obj.name();
        System.out.println(appCon.containsBean("aspectO"));
    }

    /**
     * InnerDemoApplication
     */
    @Component(value = "inDemo")
    public class InnerDemoApplication {
        @MyAnno(permissions = "stuff")
        public void name() {
            System.out.println("inside some method");
        }       
    }

}

错误


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.4.RELEASE)

2020-02-10 00:32:37.304  INFO 22236 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on kloudone-pc with PID 22236 (/media/data_drive/data/misc/aoptest2/demo/target/classes started by kloudone in /media/data_drive/data/misc/aoptest2/demo)
2020-02-10 00:32:37.307  INFO 22236 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2020-02-10 00:32:37.936  WARN 22236 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demoApplication': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
2020-02-10 00:32:37.945  INFO 22236 --- [           main] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-02-10 00:32:37.950 ERROR 22236 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demoApplication': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
    at com.example.demo.DemoApplication.main(DemoApplication.java:12) [classes/:na]
Caused by: java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
    at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:319) ~[aspectjweaver-1.9.5.jar:na]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:227) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.obtainPointcutExpression(AspectJExpressionPointcut.java:198) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:177) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:226) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:289) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:321) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:126) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:95) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:76) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:347) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:299) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:431) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    ... 14 common frames omitted


【问题讨论】:

    标签: spring spring-boot aspectj spring-aop


    【解决方案1】:

    您在reactNow(..) 中有一个建议参数MyAnno myAnno,它不会出现在您的切入点中。您需要像这样更改您的代码(未经测试,只需快速输入即可):

    @Pointcut("@annotation(myAnno)")
    public void myAnnotation(MyAnno myAnno){}
    
    @Before("myAnnotation(myAnno)")
    public void reactNow(JoinPoint jp, MyAnno myAnno) {
        System.out.println("allowed permissions are: " + myAnno.permission);
    }
    

    如果您不在其他任何地方重复使用您的切入点,或者只是内联:

    @Before("@annotation(myAnno)")
    public void reactNow(JoinPoint jp, MyAnno myAnno) {
        System.out.println("allowed permissions are: " + myAnno.permission);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-14
      • 1970-01-01
      • 2017-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多