个人粗浅认为,springboot在功能上基本是实现三个:
1.解决spring的大量xml等配置,利用的是:spring的注解扩张+spi 机制+javaConfig,也就是实现自动装配,用户也可以在此功能上开发自己的配置类Starter; 2.实现servlet3.0 规范; 3.内置servlet容器功能;
先来分析笔记的自动装配:如上面总结所说,是利用原生的spring的注解以及spi来实现的,说的精细点,就是在原来的spring 的IOC 功能+新开发特定的的spi机制+javaConfig 方式来开发的;那么在这里温习下spring的IOC;所谓的IOC,个人觉得就是一大堆组件的实现控制bean的生命周期的容器集合体,并用单例缓存池来存储实例初始化的完整对象,这些组件包括:Bean的定义类BeanDefinition,BeanDefinitionMap,扩张接口:BeanFactoryPostProcessor,BeanPostProcessor,FactoryBean,InitializingBean,DestoryBean 以及各种感知接口;
首先看下启动类注解:
看到这个重点:@Import(AutoConfigurationImportSelector.class) 这个就牵扯到 spring 的功能了,用法:注解Import 有三种用法:
- 普通bean 2.实现DeferredImportSelector接口的类 3.实现ImportSelector接口的类 4.实现ImportBeanDefinitionRegistrar的类
这里大概说一下:spring 在启动时必定会进入:
这一步就是处理加载bean的定义的,个人认为是利用:PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors --》
ConfigurationClassParser.processConfigurationClass --》ConfigurationClassParser.doProcessConfigurationClass 来递归扫描配置包下的:Component注解, PropertySource注解,ComponentScan注解,Import注解,ImportResource注解,Bean注解。。。等加载的注解,并且调用 ImportBeanDefinitionRegistrar ,BeanFactoryPostProcessor 的相关实现类去加载对应bean的信息,这就是ioc的加载类定义的关键一步;后面会记录这部分的笔记;
springboot的 @Import(AutoConfigurationImportSelector.class) 就是利用实现了 DeferredImportSelector
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
-----------------------------------------------省略
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
-----------------------------------------------省略
这里加载自动装配的所有的全限定类名;进去:
这个非常关键,记住这个:org.springframework.boot.autoconfigure.EnableAutoConfiguration
在这里会进去到断点,主要注意的是:
public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;
PropertiesLoaderUtils.loadProperties(resource) 是去该路径下解析加载这个文件的内容:
这样就可以获取到这个路径下的全限定类名了,返回:
回到:
结合就是过滤去重等操作,返回相关的类即可,回到:
这里就是spring的IOC的功能了,至此,springboot 的自动加载就此结束;所以个人认为:自动装配,就是自动加载特定路径下配置的类的 全限定类名;另外来看下配置类的实现:以;org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
为例:
以Condition为开头的就是满足一定该条件执行,总结:就是在原来的spring 的IOC 功能+新开发特定的的spi机制+javaConfig 方式实现类的定义的加载交于spring容器,至于创建就是原本spring ioc的功能;