首页 > 解决方案 > spring IOC 限定符和自动装配的奇怪行为

问题描述

我已经在 autowired et bean 方法上指定了限定符。

那么我错过了什么?

@Configuration
@EnableWebSecurity
public class CustomSecurityCOnfig  {

    @Bean
    @Qualifier("entryPoint")
    AuthenticationEntryPoint loginUrlAuthenticationEntryPoint() {
        return new LoginUrlAuthenticationEntryPoint("/login");
    }

}

我以这种方式自动连接字段

@Autowired
    @Qualifier("entryPoint")
    private AuthenticationEntryPoint loginUrlAuthenticationEntryPoint;

错误的堆栈跟踪:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.core.env.Environment' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1716) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1272) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1226) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]

编辑 我有另一个AuthenticationEntryPoint接口实现:

@Component
public class CustomAuthenticationEntryPoint extends BasicAuthenticationEntryPoint

但在我看来,它并不能解释错误(只要我指定限定符)

标签: javaspringautowiredqualifiers

解决方案


您正在混合 bean name 和 Qualifier

@Bean(name="someFancyBean")
public ClassXyx fooBar(){
    return new ClassXyz()
}

在这个例子中,方法fooBar创建了一个类型为 bean 的 bean,ClassXyx它被命名为someFancyBean. 如果你想自动连接这个bean,那么你必须使用

@Service
class SomeFancyService{
  @Autowired @Qualifier("someFancyBean") ClassXyx xyz;
}

配置类可以创建多个相同类型的 bean,但它们的名称是从函数名称派生的。除非您想重命名该 bean ,否则使用Bean注释是没有意义的。name="XYZ"

Qualifier注释用于引用同一类型的 bean 之一。

现在回到你的代码

@Configuration
@EnableWebSecurity
public class CustomSecurityCOnfig  {

    @Bean
    public AuthenticationEntryPoint entryPoint() {
        return new LoginUrlAuthenticationEntryPoint("/login");
    }

}

在您的服务中,您必须使用 Autowired as。

@Autowired
@Qualifier("entryPoint")
private AuthenticationEntryPoint loginUrlAuthenticationEntryPoint;

另外,我想再指出一件事跨包/类的 bean 可访问性。

通常,Spring IOC 创建的所有 bean 都是公共的,但它具有与 Java 类相同的访问修饰符。如果您正在创建一个具有包范围的 bean,那么您不能在另一个包中自动连接。类似地,如果一个 bean 是使用 private 创建的,那么该 bean 只能在该类中自动连接。


推荐阅读