我们都知道springboot的最大特点是:自动装配。它是怎么实现自动装配的呢?说起来比较low,用一句话概括起来就是:在META-INF/spring.factory配置文件下预先配置好需要装载入ioc容器的bean,实现自动装配。

1 绕不开的springframework

首先,理清一下spring生态的发展历程(本人是从spring4.x开始接触java的)。

在spring的整个生态中,有几个重要的接口

1 beanfactory (ioc容器的基础)

2 ApplicationContext(ioc容器的对外api,对ioc容器做扩展,包括容器的层次性,环境信息)

3 BeanFactoryPostProcessor----BeanDefinitionRegistryPostProcessor(ioc容器的扩展点)

4 BeanPostProcessor(扩展点)

5 ClassPathBeanDefinitionScanner(扫描器)

6 NamespaceHandlerSupport(配置文件解析处理器)

在spring3.0之前,spring容器的实现是通过xml配置文件的形式往ioc容器中注入bean来实现的。在之后的版本,通过引入一些相关的注解,实现通过注解往ioc容器中注入bean

在这个过程中就会设计到上面说的扫描器接口ClassPathBeanDefinitionScanner

看看源码中是怎么体现的:

当我们在xml中配置context:componentScannspring为我们做了什么呢?

springboot CLOB 类型 使用什么类型接受 springboot collector_spring


spring在解析这个标签时会注入这个Parser,我们看看这个parser做了什么?

@Override

public BeanDefinition parse(Element element, ParserContext parserContext) {

String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);

basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);

String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,

ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

// Actually scan for bean definitions and register them.
	ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
	Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
	registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

	return null;
}
这里就是去扫描我们配置的package里面包含了component注解的bean
![在这里插入图片描述]()

2 从xml到Annotation的转变

从xml驱动配置到注解驱动配置的入口:AnnotationConfigApplicationContext

springboot CLOB 类型 使用什么类型接受 springboot collector_spring_02


这个类是spring3.0的时候引入的;

首先看看这个类层次关系:

AbstractApplicationContext

GenericApplicationContext

AnnotationConfigApplicationContext

和ClassPathXmlApplicationContext有共同的抽象类,AbstractApplicationContext

具体的用法:

AnnotationConfigApplicationContext cnotallow= new AnnotationConfigApplicationContext();

context.refresh();

可以说springboot就是基于这个类做的一层封装!

在这个类的创建过程中做了什么呢?这个是基于注解驱动的关键,翻开源码,我们发现,在这个的创建过程中,会首先向ioc容器中注入6个类:

springboot CLOB 类型 使用什么类型接受 springboot collector_spring_03


springboot CLOB 类型 使用什么类型接受 springboot collector_xml_04


org.springframework.context.annotation.ConfigurationClassPostProcessor

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

org.springframework.context.event.EventListenerMethodProcessor

org.springframework.context.event.DefaultEventListenerFactory

这里最关键的类:ConfigurationClassPostProcessor是springboot实现自动装配的关键类
ConfigurationClassPostProcessor是一个BeanDefinitionRegistryPostProcessor类,在这个类里面:processConfigBeanDefinitions(BeanDefinitionRegistry registry);方法里面完成对自动装配的处理逻辑

springboot CLOB 类型 使用什么类型接受 springboot collector_spring_05


这里就是去判断 容器里面的bean是否有以下注解:

Configuration

Component

ComponentScan

Import

ImportResource

如果包含这些注解,会创建一个ConfigurationClassParser对象对这些bean做相应的处理

processDeferredImportSelectors()即是对:import注解的处理

3 再来看看springbootApplication注解
该注解由三个注解组成:
@SpringBootConfiguration----@Configuration
@EnableAutoConfiguration—@@Import(AutoConfigurationImportSelector.class),@AutoConfigurationPackage
@ComponentScan
实现自动装配是依靠EnableAutoConfiguration实现的,在前门咱们说到:
ConfigurationClassPostProcessor会对import的注解做处理
就是在这里做处理
springboot通过引入AutoConfigurationImportSelector类,在这个类中会通过
SpringFactoriesLoader.loadFactoryNames();方法对项目中的META-INF/factory.properties文件里面配置的类装在入ioc容器实现自动装配
到这里,springboot完成了对外部依赖的bean的注入
那本项目的中配置的bean又是通过什么注入到ioc容器的呢?
注意到:在SpringApplication这个类的创建过程中有个变量,primarySources,该变量存储的就是在调用SpringApplication.run()方法传入的类
通过对componentScann注解的处理,实现本项目的相应bean的注入

由于篇幅和精力有限,文中写的难免有些粗陋和简略的地方。希望致力于springboot的源码研究的同学有所帮助,也算是对自己对spring生态源码的总结