目录
3.引入ImportBeanDefinitionRegistrar的实现
4.1如果引入的类是ImportBeanDefinitionRegistrar.class的实现类
4.2如果引入的类是ImportSelector.class的实现类
4.4.2 ImportBeanDefinitionRegistrar 注册bean
服务接口
public interface IUserService {
void sayHello();
}
服务实现
public class UserServiceImpl implements IUserService {
@Override
public void sayHello() {
System.out.println("xxx");
}
}
1.直接引入
@Import({UserServiceImpl.class})
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2.引入ImportSelector的实现
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{UserServiceImpl.class.getName()};
}
}
引入selector
@Import(MyImportSelector.class)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3.引入ImportBeanDefinitionRegistrar的实现
@Import(MyImportBeanDefinitionRegistrar.class)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
注册引入类的beanDefinition
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("userService", new RootBeanDefinition(UserServiceImpl.class));
}
}
4.Import源码解析
以springBoot的启动容器
AnnotationConfigApplicationContext为例,容器创建的时候,会创建bean定义阅读器
AnnotatedBeanDefinitionReader,会往
beanFactory的
beanDefinitionMap中注册
ConfigurationClassPostProcessor的beanDefinition【Spring IOC加载过程】。他是
BeanDefinitionRegistryPostProcessor的实现类,所以他在容器调用
invokeBeanFactoryPostProcessors方法的时候会被提前实例化出来,并调用。
入口
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
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);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
解析配置类上所有import导入的类getImports(sourceClass),找到候选类
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
// 使用set跳过循环import
if (visited.add(sourceClass)) {
for (SourceClass annotation : sourceClass.getAnnotations()) {
String annName = annotation.getMetadata().getClassName();
if (!annName.equals(Import.class.getName())) {
// 递归解析非import注解,处理深层次的import
collectImports(annotation, imports, visited);
}
}
// 解析import注解的value属性
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
解析所有import直接引入的类
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
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) {
// 如果引入的类是ImportSelector.class的实现类
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
// 根据类名加载class
Class<?> candidateClass = candidate.loadClass();
// 实例化selector
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
// 延迟引入
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 调用自定义的selectImports方法,传入了@Import注解所在类的元数据,拿到导入的bean的类名
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 递归调用,如果引入的类也是importSelector或者ImportBeanDefinitionRegistrar也要解析
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
// 如果引入的类是ImportBeanDefinitionRegistrar.class的实现类
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
// 加载实现类class
Class<?> candidateClass = candidate.loadClass();
// 实例化实现类
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
// 放进map里面存放起来importBeanDefinitionRegistrars等待调用
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// 直接引入的类 存入importStack
// 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), exclusionFilter);
}
}
}
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();
}
}
}
4.1如果引入的类是ImportBeanDefinitionRegistrar.class的实现类
把它加载并实例化出来,然后把它暂存到importBeanDefinitionRegistrars里面,等待后续的解析
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
4.2如果引入的类是ImportSelector.class的实现类
加载并实例化
else {
// 调用实现类的selectImports方法,拿到需要引入的类名
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 递归处理引入的类,最终转化为引入普通的类,从4.3出口出去
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
4.3如果引入的类是其他的类
绑定引入的类和当前配置类,创建ConfigurationClass,等待后续解析
else {
// 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), exclusionFilter);
}
候选类(引入的类)作为配置类来进行处理,等待后面的解析。candidate.asConfigClass(configClass),
在ConfigurationClass中会把当前类和引入类通过importedBy进行绑定,表示这是一个被引入的类。
后续在加载beanDefiniton的时候,通过configClass.isImported来判断,如果是被引入的类,那么就注册到beanDefinitionMap中
public ConfigurationClass(MetadataReader metadataReader, @Nullable ConfigurationClass importedBy) {
this.metadata = metadataReader.getAnnotationMetadata();
this.resource = metadataReader.getResource();
this.importedBy.add(importedBy);
}
4.4从配置类加载beanDefinition
把bean定义写入到beanDefinitionMap中
this.reader.loadBeanDefinitions(configClasses);
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
// 普通引入的类从这里注册
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 处理@Bean工厂方法引入
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 处理引入其他的配置文件
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 解析前面的importBeanDefinitionRegistrars,注册需要引入的beanDefinition
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
4.4.1普通引入类注册
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isDebugEnabled()) {
logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
}
}
4.4.2 ImportBeanDefinitionRegistrar 注册bean
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
for (Map.Entry<ImportBeanDefinitionRegistrar, AnnotationMetadata> entry : registrars.entrySet()) {
entry.getKey().registerBeanDefinitions(entry.getValue(), this.registry);
}
}