【Spring注解系列05】@Import注入原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_37107022/article/details/88962331

1.@Import注解

  • 用于注入指定的类,导入组件id默认是组件的全类名。
  • 只能作用于类上。
  • 属性:value = {xx.class,xx.class}        说明:xx.class为要导入到容器中的组件

属性value中class分为三类:

     1)普通类直接注入

     2)实现ImportSelector接口的类

     3)实现ImportBeanDefinitionRegistrar接口的类

说明:

  • ImportSelector:返回需要导入的组件的全类名数组
  • ImportBeanDefinitionRegistrar:手动注册bean到容器中;

2.@Import注入原理

import类注入是通过org.springframework.context.annotation.ConfigurationClassPostProcessor后置处理器来注入的。

核心方法:postProcessBeanDefinitionRegistry

     /**
	 * Derive further bean definitions from the configuration classes in the registry.
	 */
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		int registryId = System.identityHashCode(registry);

        //判断后置处理器在registriesPostProcessed和factoriesPostProcessed中有没有被调用过
		if (this.registriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
		}
		if (this.factoriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + registry);
		}

        //调用前保存registryId,防止被重复调用
		this.registriesPostProcessed.add(registryId);

        //注入标有@configuration的对象
		processConfigBeanDefinitions(registry);
	}



    /**  构建和校验标有@configuration注解的对象
	 * Build and validate a configuration model based on the registry of
	 * {@link Configuration} classes.   
	 */
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
         //configCandidates 需要注入的所有标注@configuration的类
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();

		…………

		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
			return;
		}

		…………

		
		// Parse each @Configuration class
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
            //核心方法  解析@configuration的类
			parser.parse(candidates);
			parser.validate();

			…………
		}
		while (!candidates.isEmpty());

		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
		    …………
	}


// 进行 parse解析,获得configClass
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName));
	}


protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		…………

        //注入configuration class的上级类

		// Recursively process the configuration class and its superclass hierarchy.
		SourceClass sourceClass = asSourceClass(configClass);
		do {
            //核心方法,加载上级类,直到为null
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}


/**
	 * Apply processing and build a complete {@link ConfigurationClass} by reading the
	 * annotations, members and methods from the source class. This method can be called
	 * multiple times as relevant sources are discovered.
	 * @param configClass the configuration class being build
	 * @param sourceClass a source class
	 * @return the superclass, or {@code null} if none found or previously processed
	 */
	@Nullable
	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {

        //加载@Component组件
		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// Recursively process any member (nested) classes first
			processMemberClasses(configClass, sourceClass);
		}

        //加载@PropertySource组件
		// Process any @PropertySource annotations
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
		        …………
		}

        //加载@ComponentScan 组件
		// Process any @ComponentScan annotations
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				…………
				}
			}
		}

        //加载@Import 组件   这就是Import导入的组件
		// Process any @Import annotations
		processImports(configClass, sourceClass, getImports(sourceClass), true);


         //@ImportResource 组件
		// Process any @ImportResource annotations
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		        …………
		}

        //@Bean组件
		// Process individual @Bean methods
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
		processInterfaces(configClass, sourceClass);

		// Process superclass, if any
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// No superclass -> processing is complete
		return null;
	}

3.实例

实体类:

public class ImportBean {

}

public class ImportBean2 {

}

public class ImportBean3 {

}

public class ImportBean4 {

}

实现ImportSelector和ImportBeanDefinitionRegistrar接口类

//自定义逻辑返回需要导入的组件
public class BeanImportSelector implements ImportSelector {

    //返回值,就是到导入到容器中的组件全类名
    //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //importingClassMetadata
        //方法不要返回null值

        System.out.println(importingClassMetadata);
        return new String[]{"com.java.model.ImportBean2","com.java.model.ImportBean3"};
    }
}


public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * AnnotationMetadata:当前类的注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类;
     * 把所有需要添加到容器中的bean;调用
     * BeanDefinitionRegistry.registerBeanDefinition手工注册进来
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //指定Bean定义信息;(Bean的类型,Bean。。。)
        RootBeanDefinition beanDefinition = new RootBeanDefinition(ImportBean4.class);
        //注册一个Bean,指定bean名
        registry.registerBeanDefinition("registrar_ImportBean4", beanDefinition);
    }
}

配置类:

@Configuration
@Import({ImportBean.class, BeanImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class BeanImportConfig {


}

测试类:

public class BeanImportTest {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanImportConfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }
}


运行结果:
org.springframework.core.type.StandardAnnotationMetadata@1a0dcaa
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanImportConfig  
com.java.model.ImportBean  //普通类直接注入
com.java.model.ImportBean2 //通过ImportSelector接口注入
com.java.model.ImportBean3 //通过ImportSelector接口注入
registrar_ImportBean4      //通过ImportBeanDefinitionRegistrar注入

猜你喜欢

转载自blog.csdn.net/baidu_37107022/article/details/88962331