也谈谈springboot

我们都知道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为我们做了什么呢?
在这里插入图片描述
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
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190706190922290.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5MjAzMzM3,size_16,color_FFFFFF,t_70)

2 从xml到Annotation的转变
从xml驱动配置到注解驱动配置的入口:AnnotationConfigApplicationContext
在这里插入图片描述
这个类是spring3.0的时候引入的;
首先看看这个类层次关系:
AbstractApplicationContext
GenericApplicationContext
AnnotationConfigApplicationContext
和ClassPathXmlApplicationContext有共同的抽象类,AbstractApplicationContext
具体的用法:
AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext();
context.refresh();
可以说springboot就是基于这个类做的一层封装!
在这个类的创建过程中做了什么呢?这个是基于注解驱动的关键,翻开源码,我们发现,在这个的创建过程中,会首先向ioc容器中注入6个类:
在这里插入图片描述
在这里插入图片描述
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);方法里面完成对自动装配的处理逻辑

在这里插入图片描述
这里就是去判断 容器里面的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生态源码的总结

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值