前言

本文重点研究@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各种配置类

spring 注解注入 xml_类名

三、二阶段源码解析

#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注解对其解析排序