前言
本文重点研究@Import注解的使用与源码解析
从 SpringIOC源码:@Configuration配置类解析过程一文中,Spring通过一系列操作后,会使用ConfigurationClassParser
类的processImports
方法解析@Import
,本文源码讲解就从这里开始
一、@Import的使用
说明:只能标注在类上,属性是
Class<?>[] value()
1、注册普通bean
@Import(Person.class)
@Configuration
public class App{}
public class Person {
}
其别名是“包名.类名”
2、注册配置类
@Import({TestConfig.class)
@Configuration
public class AppConfig {
}
@Configuration
public class TestConfig {
@Bean
public Person person(){
return new Person();
}
}
注意:这时候person的别名不是“包名.类名”,是和普通的一样,而TestConfig的别名是“包名.类名”
注意:如果主配置类AppConfig中如下
@Configuration
@Import({TestConfig.class)
public class AppConfig {
@Bean
public Person person(){
return new Person();
}
}
TestConfig中的person方法不会执行,而AppConfig中的会,除非AppConfig的没有
3、注册ImportSelector的实现类
ImportSelector是Spring中导入外部配置的核心接口
public class MyImport implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{Color.class.getName()}; }
}
@Configuration
@Import(MyImport.class)
public class CarFactory { }
导入的Color的别名是cn.dao.Color 别名是“包名.类名”,
4、注册DeferredImportSelector的实现类
DeferredImportSelector是ImportSelector的子类
public interface DeferredImportSelector extends ImportSelector {
default Class<? extends Group> getImportGroup() {
return null;
}
interface Group {
void process(AnnotationMetadata metadata, DeferredImportSelector selector);
Iterable<Entry> selectImports();
}
如果我们自己的DeferredImportSelector实现Group,那么DeferredImportSelector的执行是执行其Group的process方法,否则是执行其父接口的selectImports方法
public class MyDeferredImportSelectorTwo implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("MyDeferredImportSelectorTwo");
return new String[0];
}
@Override
public Class<? extends Group> getImportGroup() {
return MyDeferredImportSelectorGroup.class;
}
private static class MyDeferredImportSelectorGroup implements Group{
private final List<Entry> imports = new ArrayList<>();
@Override
public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
System.out.println("MyDeferredImportSelectorTwo.Group");
}
@Override
public Iterable<Entry> selectImports() {
return imports;
}
}
}
控制台输出 : MyDeferredImportSelectorTwo.Group
注意单单实现Group接口还不行,还要和当前DeferredImportSelector实现类建立关系,通过其getImportGroup方法
DeferredImportSelector可以通过实现Ordered接口或者@Order注解对其解析排序
public class MyDeferredImportSelectorOne implements DeferredImportSelector, Ordered {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("MyDeferredImportSelectorOne");
return new String[0];
}
@Override
public int getOrder() {
return 1;
}
}
public class MyDeferredImportSelectorTwo implements DeferredImportSelector , Ordered {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("MyDeferredImportSelectorTwo");
return new String[0];
}
@Override
public int getOrder() {
return 2;
}
}
注册MyDeferredImportSelectorTwo和MyDeferredImportSelectorOne
@Import({MyDeferredImportSelectorOne.class,MyDeferredImportSelectorTwo.class})
@SpringBootApplication
public class SpringbootdemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(SpringbootdemoApplication.class, args);
}
}
控制台输出
MyDeferredImportSelectorTwo
MyDeferredImportSelectorOne
如果MyDeferredImportSelectorOne的getOrder返回的是2,而MyDeferredImportSelectorTwo的getOrder返回的是1
控制台输出
MyDeferredImportSelectorOne
MyDeferredImportSelectorTwo
5、注册ImportBeanDefinitionRegistrar的实现类
public interface ImportBeanDefinitionRegistrar {
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
案例
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean sign = registry.containsBeanDefinition("car”);
if(!sign){
registry.registerBeanDefinition("color", new RootBeanDefinition(Color.class));
}
}
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class CarFactory {
}
二、一阶段源码解析
1.1 源码解析
class ConfigurationClassParser {
private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = new LinkedHashMap<>();
//他是储存DeferredImportSelector的实现类的,其底层是一个包装List<DeferredImportSelectorHolder>的类
private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();
//1、一阶段解析开始
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
//2、进入底层方法processConfigurationClass
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException("", ex);
}
}
//3、一阶段结束后,执行所有缓存的DeferredImportSelector
this.deferredImportSelectorHandler.process();
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
//根据{@code@Conditional}批注确定是否应跳过项。
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//忽略代码.........
// 递归地处理配置类及其超类层次结构。
SourceClass sourceClass = asSourceClass(configClass);
do {
//进入方法
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//最终把解析到的类组装成ConfigurationClass形式放到缓存configurationClasses中
this.configurationClasses.put(configClass, configClass);
}
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//处理@Component注解
//处理@PropertySource注解
//处理@ComponentScan注解
// 处理任何@Import注释
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 处理任何@ImportResource注释
// 处理单个@Bean方法
// 处理接口上的默认方法
}
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
//循环@Import注解要value的值
for (SourceClass candidate : importCandidates) {
//如果是ImportSelector类型
if (candidate.isAssignable(ImportSelector.class)) {
//获取class
Class<?> candidateClass = candidate.loadClass();
//实例当前ImportSelector对象
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
//如果当前selector实现了Aware接口,那么执行其具体的内部回调接口
ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);
//如果value的值是DeferredImportSelector
//把当前DeferredImportSelector包装成DeferredImportSelectorHolder对象储存到缓存中
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}//如果value的值不是DeferredImportSelector
else {
//执行其selectImports方法。获取要注册的springbean全类名
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
//类型转换,可以忽略
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
//递归调用当前方法,处理要注册的类
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
//如果value是ImportBeanDefinitionRegistrar类型
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);
//把当前ImportBeanDefinitionRegistrar对象缓存起来
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// 候选类不是ImportSelector或ImportBeanDefinitionRegistrar
// 将其作为@Configuration类处理
this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
//processConfigurationClass的底层是doProcessConfigurationClass方法
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
1、获取被@Import注解标注的对象,判断他们的类型。
2、如果是ImportSelector类型:执行其selectImports方法==,获取其要注册的springBean信息,在把他们放到SourceClass集合中
3、如果是DeferredImportSelector类型;如果是把其收集起来
4、如果是ImportBeanDefinitionRegistrar类型:把他放到缓存中,以便二阶段解析注册。
5、如果既不是ImportSelector也不是ImportBeanDefinitionRegistrar:把他作为配置类。重新进入@Configuration的一阶段解析。
6、@Configuration一阶段结束后,执行所有缓存的DeferredImportSelector
1.2 DeferredImportSelector执行过程源码分析
@Configuration一阶段结束中,会把所有DeferredImportSelector包装成DeferredImportSelectorHolder对象缓存到内存中,以便一阶段完成后,会调用其process方法,执行所有的DeferredImportSelector,其执行过程如下
class ConfigurationClassParser {
private class DeferredImportSelectorHandler {
@Nullable
private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
public void process() {
//所有DeferredImportSelector的包装对象
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
//排序
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
//获取每个DeferredImportSelector的Group对象,通过其getImportGroup方法
//如果获取值为null,那么就默认储存DefaultDeferredImportSelectorGroup
//把Group对象包装成DeferredImportSelectorGrouping对象
//储存到DeferredImportSelectorGroupingHandler的缓存中
deferredImports.forEach(handler::register);
//执行每个DeferredImportSelectorGrouping的getImports方法
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
}
private class DeferredImportSelectorGroupingHandler {
private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();
private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();
public void register(DeferredImportSelectorHolder deferredImport) {
//执行当前DeferredImportSelector的getImportGroup方法获取其静态内部类Group对象
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
//判断是否能获取到group对象,如果获取不到就使用spring默认的DeferredImportSelectorGrouping
DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
(group != null ? group : deferredImport),
key -> new DeferredImportSelectorGrouping(createGroup(group)));
grouping.add(deferredImport);
this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getConfigurationClass());
}
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
Predicate<String> exclusionFilter = grouping.getCandidateFilter();
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter, false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}
其过程如下:
1、排序.我们可以通过实现Ordered接口或者@Order注解对其解析排序
2、执行每个DeferredImportSelector的getImportGroup方法获取其内部类Group,建立其与Group对象的映射关系
3、如果getImportGroup返回为null,那么其映射的Group对象就是DefaultDeferredImportSelectorGroup,在把Group对象包装成DeferredImportSelectorGrouping对象储存到DeferredImportSelectorGroupingHandler的groupings池中
private static class DefaultDeferredImportSelectorGroup implements Group {
private final List<Entry> imports = new ArrayList<>();
@Override
public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
for (String importClassName : selector.selectImports(metadata)) {
this.imports.add(new Entry(metadata, importClassName));
}
}
@Override
public Iterable<Entry> selectImports() {
return this.imports;
}
}
4、执行每个DeferredImportSelectorGrouping的getImports方法,把其返回对象放到@Configuration一阶段解析中的Import解析阶段
private static class DeferredImportSelectorGrouping {
private final DeferredImportSelector.Group group;
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
//执行静态内部类Group对象的process方法
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
//执行静态内部类Group对象的selectImports方法
return this.group.selectImports();
}
}
SpringBoot的AutoConfigurationImportSelector就是一个DeferredImportSelector
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//。。。。。。。。。
private static class AutoConfigurationGroup
implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {
private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();
//。。。。。。。。。
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
//。。。。。。。。。
}
@Override
public Iterable<Entry> selectImports() {
//。。。。。。。。。
}
//。。。。。。。。。
}
其selectImports方法返回的集合就是SpringBoot各种配置类
三、二阶段源码解析
#ConfigurationClassPostProcessor
//configClasses是一阶段缓存进去要注册的类,ImportSelector,ImportBeanDefinitionRegistrar
this.reader.loadBeanDefinitions(configClasses);
在这里我们只分析@Import注解部分
class ConfigurationClassBeanDefinitionReader {
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
//忽略代码。。。。。。。
//如果其是通过@Import注解注册过来的普通javabean,ImportBeanDefinitionRegistrar类型不会进来
if (configClass.isImported()) {
//注册其BeanDefinition到容器Spring中
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//....注册通过@bean注解标注的类
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//解析ImportBeanDefinitionRegistrar类型,执行其registerBeanDefinitions方法
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) -> registrar.registerBeanDefinitions(metadata, this.registry));
}
四、3者的不同
1、ImportSelector和ImportBeanDefinitionRegistrar的区别
public interface ImportSelector {
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
public interface ImportBeanDefinitionRegistrar {
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
ImportBeanDefinitionRegistrar这个接口作用是,用户可以实现了之后来自定义来注册需要注册的bean
。可以设置自定义的BeanNameGeneratorbean名称生成规则。
2、DeferredImportSelector和ImportSelector的区别
public interface DeferredImportSelector extends ImportSelector {
default Class<? extends Group> getImportGroup() {
return null;
}
interface Group {
void process(AnnotationMetadata metadata, DeferredImportSelector selector);
Iterable<Entry> selectImports();
}
DeferredImportSelector是ImportSelector的子接口,通过ImportSelector注册的类在通过DeferredImportSelector注册的类前。
DeferredImportSelector可以通过实现Ordered接口或者@Order注解对其解析排序