* Indicates one or more {@link Configuration @Configuration} classes to import.
*
* <p>Provides functionality equivalent to the {@code <import/>} element in Spring XML.
* Allows for importing {@code @Configuration} classes, {@link ImportSelector} and
* {@link ImportBeanDefinitionRegistrar} implementations, as well as regular component
* classes (as of 4.2; analogous to {@link AnnotationConfigApplicationContext#register}).
*
* <p>{@code @Bean} definitions declared in imported {@code @Configuration} classes should be
* accessed by using {@link org.springframework.beans.factory.annotation.Autowired @Autowired}
* injection. Either the bean itself can be autowired, or the configuration class instance
* declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly
* navigation between {@code @Configuration} class methods.
*
* <p>May be declared at the class level or as a meta-annotation.
*
* <p>If XML or other non-{@code @Configuration} bean definition resources need to be
* imported, use the {@link ImportResource @ImportResource} annotation instead.
Import

 

public @interface Import {

	/**
	 * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
	 * or regular component classes to import.
	 */
	Class<?>[] value();

}



# 例子

@Import({AnimalSelector.class , AnimalImportBeanDefinitionRegistrar.class})

ImportSelector

public interface ImportSelector {

	/**
	 * Select and return the names of which class(es) should be imported based on
	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);

}

ImportBeanDefinitionRegistrar

public interface ImportBeanDefinitionRegistrar {

	/**
	 * Register bean definitions as necessary based on the given annotation metadata of
	 * the importing {@code @Configuration} class.
	 * <p>Note that {@link BeanDefinitionRegistryPostProcessor} types may <em>not</em> be
	 * registered here, due to lifecycle constraints related to {@code @Configuration}
	 * class processing.
	 * @param importingClassMetadata annotation metadata of the importing class
	 * @param registry current bean definition registry
	 */
	void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);

}

 

@ImportResource

这个注解主要是引入xml配置,也可以引入groovy配置

xml最终通过XmlBeanDefinitionReader

public @interface ImportResource {

	@AliasFor("locations")
	String[] value() default {};

	@AliasFor("value")
	String[] locations() default {};

	Class<? extends BeanDefinitionReader> reader() default BeanDefinitionReader.class;

}

BeanDefinitionReader 

选择BeanDefinitionReader

如果是非.groovy结尾的,就是选择XmlBeanDefinitionReader

xml通过XmlBeanDefinitionReader.loadBeanDefinitions加载Bean定义

// ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromImportedResources
importedResources.forEach((resource, readerClass) -> {
	// Default reader selection necessary?
	if (BeanDefinitionReader.class == readerClass) {
		if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
			// When clearly asking for Groovy, that's what they'll get...
			readerClass = GroovyBeanDefinitionReader.class;
		}
		else {
			// Primarily ".xml" files but for any other extension as well
			readerClass = XmlBeanDefinitionReader.class;
		}
	}

	..................
	// TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations
	reader.loadBeanDefinitions(resource);
});

 

xmlbean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="employee" class="com.kq.dto.Employee" name="employee">
        <property name="id" value="6"/>
        <property name="age" value="20"/>
        <property name="name" value="admin"/>
    </bean>

</beans>

 

例子

AnimalSelector 

public class AnimalSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[] {Cat.class.getName(), Dog.class.getName()} ;
    }
}

AnimalImportBeanDefinitionRegistrar

public class AnimalImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyMapperScannerConfigurer.class);

        registry.registerBeanDefinition("animalImportBeanDefinitionRegistrar", builder.getBeanDefinition());
    }
}

MyMapperScannerConfigurer

public class MyMapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {

    private String beanName = null;

    @Override
    public void setBeanName(String name) {
        System.out.println("call setBeanName");
        this.beanName = name;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("call afterPropertiesSet");
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("call postProcessBeanDefinitionRegistry");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("call postProcessBeanFactory");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("call setApplicationContext");
    }

    public String getBeanName(){
        return this.beanName;
    }

}

AnimalConfiguration

@Configuration
@Import({AnimalSelector.class , AnimalImportBeanDefinitionRegistrar.class})
@ImportResource("xmlbean.xml")
public class AnimalConfiguration {

}

 

源码

ConfigurationClassParser

processImports 

处理@Import注解

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 {
			for (SourceClass candidate : importCandidates) {
				if (candidate.isAssignable(ImportSelector.class)) { // ImportSelector类型
					// Candidate class is an ImportSelector -> delegate to it to determine imports
					Class<?> candidateClass = candidate.loadClass(); // Import指定的class
					ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); // 对Import指定的class初始化
					ParserStrategyUtils.invokeAwareMethods(
							selector, this.environment, this.resourceLoader, this.registry); // 对相关Aware接口,赋值
					if (selector instanceof DeferredImportSelector) { // DeferredImportSelector
						this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
					}
					else { // ImportSelector 并且 非DeferredImportSelector
						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
						processImports(configClass, currentSourceClass, importSourceClasses, false);
					}
				}
				else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { // ImportBeanDefinitionRegistrar类型
					// Candidate class is an ImportBeanDefinitionRegistrar ->
					// delegate to it to register additional bean definitions
					Class<?> candidateClass = candidate.loadClass();
					ImportBeanDefinitionRegistrar registrar =
							BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
					ParserStrategyUtils.invokeAwareMethods(
							registrar, this.environment, this.resourceLoader, this.registry);
					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
				}
				else { // 既不是ImportSelector,也不是ImportBeanDefinitionRegistrar,当作@Configuration处理
					// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
					// process it as an @Configuration class
					this.importStack.registerImport(
							currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
					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();
		}
	}
}