SpringBoot自动装配原理
1 在上一文提到的启动流程中prepareContext准备上下文环境中的load方法会加载启动类
private int load(Class<?> source) {
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
load(loader);
}
/**
会判断传入的启动类是不是一个组件,有没有@Component注解,如果有则被AnnotateBeanDefinitionReader读取到,注册到beanDefinitionMap中,注册代码和spring的一样
*/
if (isComponent(source)) {
this.annotatedReader.register(source);
return 1;
}
return 0;
}
2 在refreshContext()中调用refresh()方法,自动装配在invokeBeanFactoryPostProcessors()方法中实现,核心代码是里面的PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
由于这个方法代码较多,下面粘贴这个方法中的关键代码
/**
这行代码返回的类名是internalConfigurationAnnotationProcessor
根据BeanDefinitionRegistryPostProcessor.class这个类从beanFactory中找到的
通过这个名字可以在AnnotationConfigUtils中识别到ConfigurationClassPostProcessor这个类,
自动装配的核心逻辑就是在这个类中。
ConfigurationClassPostProcessor这个类在上一篇文章ioc原理的时候有讲到,这里不再累述
*/
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//把ConfigurationClassPostProcessor放入到currentRegistryProcessors
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
/**
执行的核心方法是
postProcessor.postProcessBeanDefinitionRegistry(registry)
内的processConfigBeanDefinitions(registry);
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
2.1 processConfigBeanDefinitions(registry)方法中的解析方法parser.parse(candidates)
最终会调到sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
进行具体解析操作
/**
大体流程:
会解析到@ComponentScan,这里可以识别到我们自己定义的bean,
然后解析@Import,这里会根据启动类进行递归扫描@Import,会识别到两个@import,
然后取出里面的两个类AutoConfigurationImportSelector
和AutoConfigurationPackages.Registrar放入到一个set中进行处理。
在this.deferredImportSelectorHandler.process()会对这两个类进行处理,
调用类的getCandidateConfigurations方法,
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
getSpringFactoriesLoaderFactoryClass()方法得到EnableAutoConfiguration.class;
根据EnableAutoConfiguration.class这个类执行SpringFactoriesLoader.loadFactoryNames
加载spring.factories中根据EnableAutoConfiguration这个类获取对应的value值
得到全部自动装配的类,然后过滤掉一部分,
把需要的类封装成beanDefinition放入到beanDefinitionMap中
*/
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
//.........
// Process any @PropertySource annotations
//.........
// Process any @ComponentScan annotations
//.........
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
//.........
// Process individual @Bean methods
//.........
// Process default methods on interfaces
//.........
// Process superclass, if any
//.........
// No superclass -> processing is complete
return null;
}
2.2 processImports(configClass, sourceClass, getImports(sourceClass), filter, true)方法会执行collectImports递归寻找@Import注解
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
if (visited.add(sourceClass)) {
for (SourceClass annotation : sourceClass.getAnnotations()) {
String annName = annotation.getMetadata().getClassName();
if (!annName.equals(Import.class.getName())) {
collectImports(annotation, imports, visited);
}
}
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
2.3 解析注解完成之后parse方法会继续执行
this.deferredImportSelectorHandler.process();
处理@import取出里面的两个类,
处理AutoConfigurationImportSelector时会执行到核心方法getCandidateConfigurations
/**
getSpringFactoriesLoaderFactoryClass()方法得到EnableAutoConfiguration.class;
根据EnableAutoConfiguration.class这个类执行SpringFactoriesLoader.loadFactoryNames
加载spring.factories中根据EnableAutoConfiguration这个类获取对应的value值
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
2.4 parse方法结束后调用this.reader.loadBeanDefinitions(configClasses);会将所有需要注入的类,放入beanDefinitionMap中。