springboot中我们经常使用@Configuration 和 @Bean注解的方式去声明Bean,

@Configuration
public class SecurityAccessAutoConfiguration {

    @ConditionalOnMissingBean
    @Bean
    public ISecurityAccessUserProviderAdapter defaultSecurityAccessTokenResolver(SecurityAccessTokenProperties securityAccessTokenProperties){
        return new ConfigableSecurityAccessUserProviderAdapter(securityAccessTokenProperties);
    }

    @ConditionalOnMissingBean
    @Bean
    public ISecurityAccessTokenResolver defaultSecurityAccessTokenResolver(SecurityAccessTokenProperties securityAccessTokenProperties, ISecurityAccessUserProviderAdapter securityAccessUserProviderAdapter) {
        return new DefaultSecurityAccessTokenResolver(securityAccessTokenProperties,securityAccessUserProviderAdapter);
    }

    @Bean
    public FilterRegistrationBean securityAccessTokenFilter(ISecurityAccessTokenResolver resolver, JwtProperties jwtProperties) {
        SecurityAccessTokenFilter securityAccessTokenFilter = new SecurityAccessTokenFilter(resolver);
        FilterRegistrationBean<SecurityAccessTokenFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(securityAccessTokenFilter);
        List<String> urlPatterns = new ArrayList<>();
        String[] urls = jwtProperties.getUrlPatterns().split(",");
        for (String url : urls) {
            urlPatterns.add(url);// 拦截路径,可以添加多个
        }
        registrationBean.setUrlPatterns(urlPatterns);
        registrationBean.setOrder(0);
        return registrationBean;
    }

  
}

启动的时候 报错,方法securityAccessTokenFilter 通过入参的方式注入ISecurityAccessTokenResolver 类型的bean,由于没有找到ISecurityAccessTokenResolver类型的bean 定义导致注入失败。:

Parameter 0 of method securityAccessTokenFilter in com.gsoft.security.autoconfigurer.SecurityAccessAutoConfiguration required a bean of type 'com.gsoft.base.api.security.ISecurityAccessTokenResolver' that could not be found.


Action:

Consider defining a bean of type 'com.gsoft.base.api.security.ISecurityAccessTokenResolver' in your configuration.

但是ISecurityAccessTokenResolver类型的bean已经通过 defaultSecurityAccessTokenResolver方法声明了,怎么会提示说找不到?

查看源码发现注入是在DefaultListableBeanFactory方法实现的,使用getBean 方式获取defaultSecurityAccessTokenResolver 对应的bean实现,发现实现类竟然是ConfigableSecurityAccessUserProviderAdapter。

我们明明定义的是DefaultSecurityAccessTokenResolver,怎么会变成ConfigableSecurityAccessUserProviderAdapter

查看代码发现,@Bean注解的方法名重复了,默认情况下,使用 @Bean声明一个bean,bean的名称由方法名决定。

因此相同的bean name不会重复执行,导致只实例化ISecurityAccessUserProviderAdapter 类型的bean,而ISecurityAccessTokenResolver 类型并未实例化,导致注入失败。

解决办法: 修改其中的一个defaultSecurityAccessTokenResolver方法的名称为 configableSecurityAccessUserProviderAdapter,避免bean的名称重复,问题解决。

@Configuration
public class SecurityAccessAutoConfiguration {
    
    @ConditionalOnMissingBean
    @Bean
    public ISecurityAccessUserProviderAdapter configableSecurityAccessUserProviderAdapter(SecurityAccessTokenProperties securityAccessTokenProperties){
        return new ConfigableSecurityAccessUserProviderAdapter(securityAccessTokenProperties);
    }

    @ConditionalOnMissingBean
    @Bean
    public ISecurityAccessTokenResolver defaultSecurityAccessTokenResolver(SecurityAccessTokenProperties securityAccessTokenProperties, ISecurityAccessUserProviderAdapter securityAccessUserProviderAdapter) {
        return new DefaultSecurityAccessTokenResolver(securityAccessTokenProperties,securityAccessUserProviderAdapter);
    }

    @Bean
    public FilterRegistrationBean securityAccessTokenFilter(ISecurityAccessTokenResolver resolver, JwtProperties jwtProperties) {
        SecurityAccessTokenFilter securityAccessTokenFilter = new SecurityAccessTokenFilter(resolver);
        FilterRegistrationBean<SecurityAccessTokenFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(securityAccessTokenFilter);
        List<String> urlPatterns = new ArrayList<>();
        String[] urls = jwtProperties.getUrlPatterns().split(",");
        for (String url : urls) {
            urlPatterns.add(url);// 拦截路径,可以添加多个
        }
        registrationBean.setUrlPatterns(urlPatterns);
        registrationBean.setOrder(0);
        return registrationBean;
    }
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐