版权声明:本文为博主原创文章,未经博主允许不得转载。 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注入