@Import用法
@Import的value值,可以是 普通bean、ImportSelector类、ImportBeanDefinitionRegistrar类
配置类
package org.hopehomi.boot.config;
import org.hopehomi.boot.config.selector.MyImportSelector;
import org.hopehomi.boot.model.BeanByImport;
import org.hopehomi.core.tool.support.ForDebuggerImportBeanDefinitionRegistrar;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author Ledison
* @date 2023/3/16
*/
@Configuration(proxyBeanMethods = false)
@Import({ForDebuggerImportBeanDefinitionRegistrar.class, BeanByImport.class, MyImportSelector.class})
// @ImportAutoConfiguration 如果没有写value,会去spring.factories里面找key为当前类名的value
// 如果写了value,和@Import一样
@ImportAutoConfiguration
public class MyConfig {
public MyConfig() {
System.out.println("MyConfig construct");
}
@Bean(initMethod = "doInit")
public ConfigInnerBean getConfigInnerBean() {
return new ConfigInnerBean();
}
}
- 普通bean
package org.hopehomi.boot.model;
/**
* @author Ledison
* @date 2023/3/24
*/
public class BeanByImport {
}
- ImportBeanDefinitionRegistrar
package org.hopehomi.core.tool.support;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* @author Ledison
* @date 2023/3/21
*/
public class ForDebuggerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
System.out.println("ForDebuggerImportBeanDefinitionRegistrar registerBeanDefinitions - B");
BeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClassName("org.hopehomi.core.tool.support.HopeRegisterBean");
registry.registerBeanDefinition("HopeRegisterBean", bd);
}
}
- ImportSelector
package org.hopehomi.boot.config.selector;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* {@link org.hopehomi.boot.model.BeansByImportSelector}
*
* @author Ledison
* @date 2023/3/24
*/
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"org.hopehomi.boot.model.BeansByImportSelector"};
}
}
原理
三个类型都是通过ConfigurationClassParser的processImports来解析,调用方可以是@ComponentScan扫描类、spring自动装配类
- 引入类为ImportSelector
通过构造器实例化类,判断是否为DeferredImportSelector的实现(延迟引入,spring的自动装配AutoConfigurationImportSelector就实现了这个接口),如果是DeferredImportSelector的实现,放入延迟Selector集合后面处理;如果不是DeferredImportSelector的实现,调用ImportSelector的selectImports方法,返回类名数组,加载解析类名(如果没有引入该类,会报错),最后这些类名数组再递归调用processImports方法
- 引入类为ImportBeanDefinitionRegistrar
通过构造器实例化类,加入到ConfigurationClass的importBeanDefinitionRegistrars集合中,解析完所有加载类之后,在进行处理。
ConfigurationClassPostProcessor - processConfigBeanDefinitions - this.reader.loadBeanDefinitions(configClasses);
执行过程在ImportSelector之后
这里的configClass.getImportBeanDefinitionRegistrars()。就是之前解析出来待处理的importBeanDefinitionRegistrars
执行回调
- 引入类为普通类
执行processConfigurationClass方法,引入的类会判断是否存在注解@Component、@PropertySources、@ComponentScans、@Import、@ImportResource、@Bean Method,存在的话进行对应处理。最后将类名放到ConfigurationClassParser.configurationClasses中,详细解析源码可看之前的文章。在这里没有进行类的实例化操作
@ImportAutoConfiguration用法
@ImportAutoConfiguration 如果没有写value,会去spring.factories里面找key为当前类名的value
如果写了value,和@Import一样,不会通过spring.factories加载
@ImportAutoConfiguration 和 @Import不要同时在配置类使用,否则@Import里面的value会实例化两次
配置类
package org.hopehomi.boot.config;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.context.annotation.Configuration;
/**
* @author Ledison
* @date 2023/3/24
*/
// @ImportAutoConfiguration 如果没有写value,会去spring.factories里面找key为当前类名的value
// 如果写了value,和@Import一样
@ImportAutoConfiguration
@Configuration(proxyBeanMethods = false)
public class MyImportAutoConfiguration {
}
注入类
package org.hopehomi.boot.model;
import org.hopehomi.boot.config.MyImportAutoConfiguration;
/**
* @author Ledison
* @date 2023/3/24
*/
public class BeanByImportAutoConfiguration extends MyImportAutoConfiguration {
public BeanByImportAutoConfiguration() {
System.out.println("BeanByImportAutoConfiguration construct");
}
}
spring.factories
原理
进入@ImportAutoConfiguration,可以看到@Import(ImportAutoConfigurationImportSelector.class)
ImportAutoConfigurationImportSelector是DeferredImportSelector的实现类,具体源码就不分析了,可以通过延迟加载Selector的步骤找到这个实现类看逻辑