这里的主要逻辑其实还是在SpringFrame里面实现
并没有多少特殊的地方
咱们继续进入到AbstarctApplicationContext的refresh方法中去看看
SpringBoot的这一块具体加载BeanDefinetions主要在invokeBeanFactoryPostProcessors该方法中
加载完了之后进行实例化就实现了自动化配置
所以咱们主要看加载BeanDefinetions
并且Spring代码的执行都是一环扣一环,相当的紧凑不会出现两个毫无关联的逻辑放在一个方法里面的情况
说到自动装配咱们就得看看
invokeBeanFactoryPostProcessors方法
这方法看上去很长其实做的事情很简单大过程其实就做了两步
1.处理Spring.factories中加载进来的process,将ConfigurationClassPostProcessor注册。当然还有一些其他的操作,不过可以先不管那些。
2.使用ConfigurationClassPostProcessor去parse解析注解类
看下具体的代码
//这里是第一步
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//主要逻辑注册ConfigurationClassPostProcessor,这个bean是在SpringApplication的构造函数中初始化进去的。
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
//这里是第二步,执行ConfigurationClassPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
上面的代码就完成了具体的两个步骤咱们继续进入到process里面看看具体怎么加载
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.调用bean的方法
* 咱们看下postProcessBeanDefinitionRegistry方法里面的具体执行逻辑processConfigBeanDefinitions方法
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
在processConfigBeanDefinitions这个方法里面首先做的一件事情其实就是通过
SpringBoot的启动配置类进行解析,里面有一个具体的实现方法parse。该方法实现类在ConfigurationClassParser
咱们进去看一眼
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
//解析注解配置类,从启动类里面配置的那个配置类开始。一直循环直到结束。
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
//传说中的SpringBoot八爪鱼,通过SPI去获取各个自动配置具体实现类。
processDeferredImportSelectors();
}
上面的方法分为两步
1.加载项目中的注解beanDefiniton
2.加载自动配置的beanDefiniton
第一步的实现代码
在doProcessConfigurationClass里面
具体做了下面三件事
1.处理PropertySource注解
2.处理ComponentScan注解
3.处理Import注解
做完上面三件事,咱们项目里面的bean以及import进来的class就都将信息注册到了BeanDefinitons,可以用于后面的实例化
咱们再看一眼
processDeferredImportSelectors这个方法加载外部配置类,实现自动配置。
其实就是通过EnableAutoConfiguration注解中import进来的AutoConfigurationImportSelector类去处理
执行里面的selectImports方法,然后去Spring.factories中加载EnableAutoConfiguration的配置类。还是通过Springle中实现的SPI。
做完上面这些操作基本整个流程就结束了
##自动配置
咱们看一个mybatis-plus的配置类的代码
@Configuration//标明这是一个配置类
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})//存在上面两个classs的时候执行
@ConditionalOnSingleCandidate(DataSource.class)//datasource是单例
@EnableConfigurationProperties(MybatisPlusProperties.class)//配置类
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisPlusAutoConfiguration {
//其实就是通过上面这些注解的使用执行相应的逻辑,所以如果咱们觉得自带的配置不好用
//完全可以自己覆盖,然后实现一个自己的
欢迎扫码加入知识星球继续讨论