Аспекты, не работающие в приложении весенней загрузки

Я создаю загрузочное приложение Spring с аспектами, но оно не работает. Его не забирают.

Я определил EnableAspectJAutoProxy в пользовательском классе конфигурации.

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {

@Bean
public ModelMapper modelMapper() {
    return new ModelMapper();
}

Проанализировав несколько решений проблемы переполнения стека, я обнаружил, что добавление @Component может решить мою проблему, но когда я добавляю @Component, мое приложение не запускается.

пожалуйста, найдите ошибку ниже-

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'projectingArgumentResolverBeanPostProcessor' defined in class path resource [org/springframework/data/web/config/ProjectingArgumentResolverRegistrar.class]: BeanPostProcessor before instantiation of bean failed
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:277) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:805) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[spring-context-6.1.4.jar:6.1.4]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.3.jar:3.2.3]
    at com.dimensions.inc.personalTrackerbank.PersonalTrackerbankApplication.main(PersonalTrackerbankApplication.java:10) ~[classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': warning no match for this type name: com.dimensions.inc.personalTrackerbank.bankInfoInterface [Xlint:invalidAbsoluteTypeName]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:607) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:409) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1335) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1165) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans(BeanFactoryAdvisorRetrievalHelper.java:91) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findCandidateAdvisors(AbstractAdvisorAutoProxyCreator.java:111) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors(AnnotationAwareAspectJAutoProxyCreator.java:92) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:101) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:280) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:1130) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:1105) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:511) ~[spring-beans-6.1.4.jar:6.1.4]
    ... 14 common frames omitted
Caused by: java.lang.IllegalArgumentException: warning no match for this type name: com.dimensions.inc.personalTrackerbank.bankInfoInterface [Xlint:invalidAbsoluteTypeName]
    at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:319) ~[aspectjweaver-1.9.21.jar:na]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:223) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.obtainPointcutExpression(AspectJExpressionPointcut.java:194) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:173) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:233) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:295) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:327) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:128) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:97) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:78) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:366) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:318) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:438) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1789) ~[spring-beans-6.1.4.jar:6.1.4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.4.jar:6.1.4]

Мой код -

файл ресурсов -

@RestController
@RequestMapping("/data")
public class PtbBankResource {

     @GetMapping("/ret")
     @ValidateUser(headerName = "Authorization")
     public ResponseEntity<?> getCall()
     {
          return ResponseEntity.ok().body("data Successfull");
     }
}

пользовательская аннотация -

@Component
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateUser {    
    String headerName() default "";
}

Класс аспекта -

@Aspect
public class AuthAspect {

private static final Logger logger = LoggerFactory.getLogger(AuthAspect.class);

@Autowired
PtbUtils ptbUtils;

@Around(value = "execution(* *(..)) && @annotation(ValidateUser)")
public Object authValidation(ProceedingJoinPoint joinPoint, ValidateUser validateUser) throws Throwable
{
    logger.info("Inside authValidation class");

    String headerName = validateUser.headerName().isEmpty() ? HttpHeaders.AUTHORIZATION : validateUser.headerName();
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

    logger.info("headerName = " + headerName);
    logger.info("request = " + request);
    String token = request.getHeader(headerName);
    logger.info("token = " + token);
    Boolean value = ptbUtils.validateJwtToken(token);
    System.out.println("value = " + value);
    return joinPoint.proceed();
}
1
0
543
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Удалите аннотацию @Component из вашего класса @interface и добавьте ее в класс @Aspect.

Кстати, вместо создания специального аспекта для аутентификации и авторизации пользователя я настоятельно рекомендую вместо этого использовать модуль Spring Security и поместить свою собственную логику аутентификации в собственный PermissionEvaluator. Или, если вы упомянули OAuth в своем фрагменте, проверьте, будет ли достаточно настройки безопасности Spring OAuth2.

Дополнительную информацию можно найти на https://www.baeldung.com/spring-security-create-new-custom-security-expression и https://www.baeldung.com/spring-security-oauth

Я выполнил упомянутые выше шаги по перемещению @Component из интерфейса в класс Aspect, но при запуске приложения все равно получил ту же ошибку. Я использую версию Spring-Boot 3.2.3 (если это поможет). Я разрабатываю этот проект, чтобы освежить свое понимание Spring AOP, и нет ничего лучше, чем реализовать выборку токена из заголовков и проверку его подлинности.

Shikhar Gupta 30.03.2024 13:01

Я обновил свой ответ относительно аннотации @Around.

Michiel 30.03.2024 14:30

Удаление execution(* (..)) не влияет на аспекты Spring AOP, оно только изменит поведение в собственных аспектах Aspectj, но расширит диапазон, а не сузит его, как вы думаете. В Spring AOP все советы неявно относятся к типу execution. Явное определение части execution, по моему мнению, даже хорошая практика, потому что всегда может случиться так, что в будущем вы перейдете от простого Spring AOP к полноценному AspectJ.

kriegaex 30.03.2024 15:46

Я предполагаю, что ваш pointcut слишком широк и ориентирован на слишком много классов. Spring AOP может проверять @annotation только во время выполнения, а это означает, что ему необходимо проверять все классы, включая внутренние компоненты Spring и сторонние компоненты, что может привести к проблемам «курица против яйца» во время инициализации и подключения компонентов. Просто ограничьте область действия pointcut следующим образом:

... && within(my.app.base_package..*)

В родном AspectJ это не будет проблемой.

P.S.: Я не являюсь активным пользователем Spring, но у AFAIK Spring есть собственная среда проверки. Вы, конечно, можете использовать АОП как вполне допустимый вариант использования (без каламбура), но есть вероятность, что встроенные возможности вам достаточно хороши.

Spring использует валидатор Hibernate в качестве среды проверки, но он работает с POJO. Я добавил решение.

Shikhar Gupta 30.03.2024 19:02
Ответ принят как подходящий

Изучив ответы и внимательно прочитав официальную документацию, я обнаружил, что для значения @annotation требуется объект пользовательской аннотации, а не класс.

Ссылка — https://docs.spring.io/spring-framework/docs/2.5.x/reference/aop.html#aop-ataspectj-around-advice (Заголовок 6.2.4)

поэтому мой класс Aspect становится ->

@Aspect
@Component
public class AuthAspect {

private static final Logger logger = LoggerFactory.getLogger(AuthAspect.class);

@Autowired
PtbUtils ptbUtils;

@Around("@annotation(validateUser)")
public Object authValidation(ProceedingJoinPoint joinPoint, ValidateUser validateUser) throws Throwable
{
    logger.info("Inside authValidation class");

    String headerName = validateUser.headerName().isEmpty() ? HttpHeaders.AUTHORIZATION : validateUser.headerName();
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

    logger.info("headerName = " + headerName);
    logger.info("request = " + request);
    String token = request.getHeader(headerName);
    logger.info("token = " + token);
    Boolean value = ptbUtils.validateJwtToken(token);
    System.out.println("value = " + value);
    return joinPoint.proceed();
}
}

Редактировать -

Чтобы исправить первоначальную проблему, как указано в моем вопросе, потребовалось удалить тег @Component из @interface.

После удаления @Component из @interface и последующего добавления его в класс Aspect возникла новая ошибка:

error at::0 formal unbound in pointcut

Чтобы это исправить, сработало решение, представленное до того, как «Редактировать».

Ваш ответ не совсем правильный и не решает исходную проблему с ошибкой в ​​вопросе: Конечно, что-то вроде @annotation(my.package.MyAnnotation) тоже возможно, если вам не нужна ссылка на аннотацию. В вашем случае он вам действительно нужен, и здесь правильно использовать имя параметра связанного метода вместо полного имени класса. Но прежде чем это исправить, ваше сообщение об ошибке должно было быть error at ::0 formal unbound in pointcut, а не ошибка в вашем вопросе. Вы еще забыли @Component в своем аспекте в вопросе, исправляйте это здесь.

kriegaex 31.03.2024 11:15

Спасибо, что выделили. Да, есть еще несколько обновлений, предложенных @michiel. Обновляю то же самое в своем ответе.

Shikhar Gupta 31.03.2024 17:08

Другие вопросы по теме