什么是自动装配
springboot 定义一套接口规范,这套规范规定:springboot 在启动时会扫描外部引用 jar 包中的 META-INF/spring.factories 文件,将文件中配置的类型信息加载到 spring 容器,并执行类中定义的各种操作 对于外部 jar 来说,只需要按照 springboot 定义的标准,就能将自己的功能装置进 springboot
自动装配的作用
自动装配能够很大程度减少开发人员对 bean 的装配工作,只需要通过把对应的 bean 对象配置到对应工程下 META-INF/spring.factories,就能够装配到 spring 容器中
DeferredImportSelector 接口分析
springboot 的 AutoConfigurationImportSelector 类实现 DeferredImportSelector 接口,并且实现内部接口 Group,重写 Group 的 process() 和 selectImports() 方法 DeferredImportSelector 接口的 process() 和 selectImports() 方法,在 spring 调用bean定义注册后置处理器的时候会调用这个两个方法 process() 方法会获取 spring.factories 中用户定义的 bean 列表,selectImports() 方法获取将 process() 方法获取的 bean 对象列表包装成 Group 接口的内部类 Entry 对象 在获取到 Entry 对象列表之后,将这些 bean 对象注册到容器中 之后 spring 会对容器中的 bean 对象列表进行实例化和属性填充
public interface DeferredImportSelector extends ImportSelector {
@Nullable
default Class < ? extends Group > getImportGroup ( ) {
return null ;
}
interface Group {
void process ( AnnotationMetadata metadata, DeferredImportSelector selector) ;
Iterable < Entry > selectImports ( ) ;
class Entry {
private final AnnotationMetadata metadata;
private final String importClassName;
public Entry ( AnnotationMetadata metadata, String importClassName) {
this . metadata = metadata;
this . importClassName = importClassName;
}
public AnnotationMetadata getMetadata ( ) {
return this . metadata;
}
public String getImportClassName ( ) {
return this . importClassName;
}
@Override
public boolean equals ( @Nullable Object other) {
if ( this == other) {
return true ;
}
if ( other == null || getClass ( ) != other. getClass ( ) ) {
return false ;
}
Entry entry = ( Entry ) other;
return ( this . metadata. equals ( entry. metadata) && this . importClassName. equals ( entry. importClassName) ) ;
}
@Override
public int hashCode ( ) {
return ( this . metadata. hashCode ( ) * 31 + this . importClassName. hashCode ( ) ) ;
}
@Override
public String toString ( ) {
return this . importClassName;
}
}
}
}
自动装配实现原理
AutoConfigurationGroup 实现类分析
spring 在容器刷新的时候会调用这两个方法 调用两个方法之后,用户定义的 bean 对象会被注入到 spring 容器中,之后会统一对bean对象进行实例化和属性填充
@Override
public void process ( AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert . state ( deferredImportSelector instanceof AutoConfigurationImportSelector ,
( ) -> String . format ( "Only %s implementations are supported, got %s" ,
AutoConfigurationImportSelector . class . getSimpleName ( ) ,
deferredImportSelector. getClass ( ) . getName ( ) ) ) ;
AutoConfigurationEntry autoConfigurationEntry = ( ( AutoConfigurationImportSelector ) deferredImportSelector)
. getAutoConfigurationEntry ( annotationMetadata) ;
this . autoConfigurationEntries. add ( autoConfigurationEntry) ;
for ( String importClassName : autoConfigurationEntry. getConfigurations ( ) ) {
this . entries. putIfAbsent ( importClassName, annotationMetadata) ;
}
}
@Override
public Iterable < Entry > selectImports ( ) {
if ( this . autoConfigurationEntries. isEmpty ( ) ) {
return Collections . emptyList ( ) ;
}
Set < String > allExclusions = this . autoConfigurationEntries. stream ( )
. map ( AutoConfigurationEntry :: getExclusions ) . flatMap ( Collection :: stream ) . collect ( Collectors . toSet ( ) ) ;
Set < String > processedConfigurations = this . autoConfigurationEntries. stream ( )
. map ( AutoConfigurationEntry :: getConfigurations ) . flatMap ( Collection :: stream )
. collect ( Collectors . toCollection ( LinkedHashSet :: new ) ) ;
processedConfigurations. removeAll ( allExclusions) ;
return sortAutoConfigurations ( processedConfigurations, getAutoConfigurationMetadata ( ) ) . stream ( )
. map ( ( importClassName) -> new Entry ( this . entries. get ( importClassName) , importClassName) )
. collect ( Collectors . toList ( ) ) ;
}
获取 spring.factories 中的 bean 对象列表
protected AutoConfigurationEntry getAutoConfigurationEntry ( AnnotationMetadata annotationMetadata) {
if ( ! isEnabled ( annotationMetadata) ) {
return EMPTY_ENTRY ;
}
AnnotationAttributes attributes = getAttributes ( annotationMetadata) ;
List < String > configurations = getCandidateConfigurations ( annotationMetadata, attributes) ;
configurations = removeDuplicates ( configurations) ;
Set < String > exclusions = getExclusions ( annotationMetadata, attributes) ;
checkExcludedClasses ( configurations, exclusions) ;
configurations. removeAll ( exclusions) ;
configurations = getConfigurationClassFilter ( ) . filter ( configurations) ;
fireAutoConfigurationImportEvents ( configurations, exclusions) ;
return new AutoConfigurationEntry ( configurations, exclusions) ;
}
流程总结
springboot 自动装配的流程 spring 容器刷新对 DeferredImportSelector 的处理