Java NoSuchBeanDefinitionException,但定义了bean

Java NoSuchBeanDefinitionException,但定义了bean,java,spring,spring-boot,Java,Spring,Spring Boot,我试图使用基于Java的配置而不是本文中的XML配置将配置导入Spring Boot: 我得到以下例外情况: org.springframework.beans.factory.unsatifiedDependencyException:创建名为“postAuthorizeAdvisor”的bean时出错,该bean在类路径资源[test/project/security/aop/AopSecurityConfiguration.class]中定义:未满足的依赖项通过索引为0的构造函数参数表示

我试图使用基于Java的配置而不是本文中的XML配置将配置导入Spring Boot:

我得到以下例外情况:

org.springframework.beans.factory.unsatifiedDependencyException:创建名为“postAuthorizeAdvisor”的bean时出错,该bean在类路径资源[test/project/security/aop/AopSecurityConfiguration.class]中定义:未满足的依赖项通过索引为0的构造函数参数表示[org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor]::未找到依赖项类型为[org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor]的符合条件的bean:应至少有1个bean符合此项的autowire候选项 dependency.dependency annotations:{};嵌套异常为org.springframework.beans.factory.NoSuchBean定义异常:没有[org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor]类型的合格bean为依赖项找到:应至少有1个bean符合此依赖项的autowire候选。依赖项批注:{}

以下是包含这些bean定义的类:

@Configuration
public class AopSecurityConfiguration {
    @Bean
    public MethodSecurityInterceptor methodSecurityInterceptor(AuthenticationManager authenticationManager) {
        MethodSecurityInterceptor msi = new MethodSecurityInterceptor();
        msi.setAuthenticationManager(authenticationManager);
        msi.setValidateConfigAttributes(false);

        MethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();

        ExpressionBasedAnnotationAttributeFactory factory = new ExpressionBasedAnnotationAttributeFactory(handler);
        ExperimentalPrePostAnnotationSecurityMetadataSource metadataSource = new ExperimentalPrePostAnnotationSecurityMetadataSource(factory);
        msi.setSecurityMetadataSource(metadataSource);

        ExpressionBasedPreInvocationAdvice advice = new ExpressionBasedPreInvocationAdvice();
        advice.setExpressionHandler(handler);
        AccessDecisionVoter<?> voter = new PreInvocationAuthorizationAdviceVoter(advice);
        AccessDecisionManager manager = new AffirmativeBased(Collections.singletonList(voter));
        msi.setAccessDecisionManager(manager);

        return msi;
    }

    @Bean
    public Advisor preAuthorizeAdvisor(MethodSecurityInterceptor methodSecurityInterceptor) {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(@(@org.springframework.security.access.prepost.PreAuthorize *) * *.* (..))");
        return new DefaultPointcutAdvisor(pointcut, methodSecurityInterceptor);
    }

    @Bean
    public Advisor preFilterAdvisor(MethodSecurityInterceptor methodSecurityInterceptor) {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(@(@org.springframework.security.access.prepost.PreFilter *) * *.* (..))");
        return new DefaultPointcutAdvisor(pointcut, methodSecurityInterceptor);
    }

    @Bean
    public Advisor postAuthorizeAdvisor(MethodSecurityInterceptor methodSecurityInterceptor) {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(@(@org.springframework.security.access.prepost.PostAuthorize *) * *.* (..))");
        return new DefaultPointcutAdvisor(pointcut, methodSecurityInterceptor);
    }

    @Bean
    public Advisor postFilterAdvisor(MethodSecurityInterceptor methodSecurityInterceptor) {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(@(@org.springframework.security.access.prepost.PostFilter *) * *.* (..))");
        return new DefaultPointcutAdvisor(pointcut, methodSecurityInterceptor);
    }
}
编辑

我可以通过删除WebSecurity配置适配器的实现来解决此问题。这删除了AuthenticationManagerBuilder和HttpSecurity的配置

对于身份验证管理器,我的理解是,我需要创建一个AuthenticationProvider来处理用户的身份验证,因此我使用DaoAuthenticationProvider和InMemoryUserDetailsManager来创建一个简单的提供程序。这是以前使用AuthenticationManagerBuilder#inMemoryAuthentication完成的


我不确定我需要如何设置HttpSecurity的实例,以便使用表单登录,我可以使用WebSecurityConfigureAdapter进行表单登录。

您必须将
@Autowired
注释放在使用
methodSecurityInterceptor
的方法的顶部

例如:

@Bean
@Autowired
public Advisor postAuthorizeAdvisor(MethodSecurityInterceptor methodSecurityInterceptor) {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression("execution(@(@org.springframework.security.access.prepost.PostAuthorize *) * *.* (..))");
    return new DefaultPointcutAdvisor(pointcut, methodSecurityInterceptor);
}

我已经找到了如何更正此问题的方法,但不完全确定其原因,但确实如此。我删除了AopSecurityConfiguration类,并将methodSecurityInterceptor方法移动到我的WebSecurityConfigureAdapter实现中,并删除了authenticationManager参数。在该方法中,我现在调用的authenticationManager方法Web安全配置适配器

这样做允许我创建自定义的预/后授权注释,我可以使用RulesRelation注释和/或注释


不确定原始博客上描述的切入点顾问需要做什么,也许这是以前版本所需要的,但现在不再需要了?

它抱怨的只是postAuthorizeAdvisor方法吗?尝试对这个方法进行注释,然后再次运行程序,看看它是否抱怨其他方法ods?一旦您注释掉了该方法,那么如果其他方法也导致类似的异常,那么请尝试将@Autowired添加到postAuthorizeAdvisor方法中的MethodSecurityInterceptor参数中,以连接到MethodSecurityInterceptor beanI注释掉了每个advisor方法,它们都给出了类似的异常。然后我尝试MethodSecurityInterceptor参数上的自动连线批注,但我收到一个错误,指示不允许存在该批注。因此我尝试将其放在advisor方法上,但收到了相同的异常。您确定这是完整堆栈跟踪吗?在MethodSecurityInterceptor bean上进行了一些后处理ks安全数据存储和访问决策管理器。如果其中任何一个都不好,则创建bean时会出现异常。不,这不是完整的stacktrace,我将其裁剪为我认为相关的部分。我已更新帖子以包含完整的stacktrace。而且从未调用“methodSecurityInterceptor”方法。@Smogers在问题的评论部分提出了这一点。当我这样做时,我收到了与没有自动连线批注时相同的异常情况。此外,我在其他地方使用了类似的模式,但没有自动连线批注,它工作正常。我发现,一旦我删除了我定义的WebSecurityConfigureAdapter实现,我就能够克服这个问题(我仍然不明白为什么这样做有效),但这带来了它自己的一系列问题。
@Bean
@Autowired
public Advisor postAuthorizeAdvisor(MethodSecurityInterceptor methodSecurityInterceptor) {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression("execution(@(@org.springframework.security.access.prepost.PostAuthorize *) * *.* (..))");
    return new DefaultPointcutAdvisor(pointcut, methodSecurityInterceptor);
}