今天在看Spring中ProviderManager创建过程的源码时,调试到org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration类里的setGlobalAuthenticationConfigurers()方法:
@Autowired(required = false)
public void setGlobalAuthenticationConfigurers(List<GlobalAuthenticationConfigurerAdapter> configurers) {
configurers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.globalAuthConfigurers = configurers;
}
虽然知道@Autowired这个注解会自动填入参数,但是在类文件里找了一遍,没有发现List<GlobalAuthenticationConfigurerAdapter>
类型的Bean。
后来查了资料才发现,这个类里有3个继承于GlobalAuthenticationConfigurerAdapter类的子类的Bean。
@Bean
public static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(
ApplicationContext context) {
return new EnableGlobalAuthenticationAutowiredConfigurer(context);
}
@Bean
public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(
ApplicationContext context) {
return new InitializeUserDetailsBeanManagerConfigurer(context);
}
@Bean
public static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer(
ApplicationContext context) {
return new InitializeAuthenticationProviderBeanManagerConfigurer(context);
}
这三个类的Bean实例,刚好是上面那个方法里的List类型参数的集合内容。由此猜测,@Autowired会查询到List<T>
所对应的T类型Bean,并全部添加到这个List中,再作为参数填入。
于是,写了个测试类验证了一下。
@Configuration
public class SecurityConfig {
@Bean
public static AbstractXXX xxx1(){
return new AbstractXXX();
}
@Bean
public static AbstractXXX xxx2(){
return new AbstractXXX();
}
@Autowired
public void setConfigurers(List<AbstractXXX> configurers) {
System.out.println(configurers.size());
configurers.sort(AnnotationAwareOrderComparator.INSTANCE);
}
public static class AbstractXXX{
}
}
注释:
@Bean需要@Configuration的配合才能生效
@Bean注解的方法加上static可以确保优先生成,避免"The dependencies of some of the beans in the application context form a cycle"(依赖循环错误)
@Bean注解的方法可以在其它类,只要是被Spring容器托管的Bean对象就行。
自定义类AbstractXXX一样可以在其它类或当独文件,在同一个类中就需要static关键字标识。