课程内容:
1.从spring IOC到springboot的原理
2.DeferredImportSelector对Bean的加载顺序的影响
3.SpringBoot自动配置源码深入分析
4.如何在自定义配置类上进行定制扩展
5.实现自定义starter完成自动配置
可以点击下面有道云笔记链接,格式可能更好看一些
1.Springboot像什么:像一个脚手架
springboot只是帮助我们去配置Bean,也就是帮助我们去集成第三方框架的Bean,但是Bean的管理还是交给Spring
Spring的过程分成两部分:类---BeanDefinition---BeanFactory----Bean
BeanDefinition变成Bean利用的就是反射的原理
2.当每集成一个框架的时候,一般都是EnableXXXX,里面都是@Import
@Import分为三种:@Import(类) @Import(ImportSelector)@Impor(ImportBeanDefinitionRegistry)
3.我们有什么办法能批量注册Bean吗?
@Import(ImportSelector)可以吗?也可以也不可以。
可以。我们可以重写slector方法,返回数组的时候,里面包括类的路径名,Spring可以去扫描并加载
不可以。比如SqlSessionFactory,当我们自定义一个Bean SqlSessionFactory去扩展的时候,按常理是想加载我们自己自定义的,但是我们不能保证加载的顺序,所以就无法保证加载的是我们自定义的
这个时候我们就需要使用到ImportSelector的变种,也就是他的子类:DeferredImportSelector
利用DeferredImportSelector就可以加载自己定义的SqlSessionFactory,当加载到mybatis的时候,因为ConditionalOnBean,就不会去加载mybatis的SqlSessionFactory了
4.DeferredImportSelector是怎么做到的呢?
Deferred是延迟,推迟的意思,当我们都解析了所有的@Compoent@Bean等这些注解后,最后才去解析,就确保了使用的是我们自定义的SqlSessionFactory
5.实现DeferredImportSelector的步骤:
首先调用getImportGroup,如果返回的是null,就调用selectImports
如果返回的是实现了DeferredImportSelector.Group的Group,就调用Group的selectImports
Group组的作用就是SpringBoot在同一个组的Bean,可以实现组内对Bean调整顺序
6.因为SpringBoot中有很有的Bean,这些Bean的路径保存在jar包下Spring.factories中,DeferredImportSelector去读取,然后读取到selectImports的数组中,排序,返回给spring 并让其去加载成BeanDefinition
/***
* 延迟 特性, 分组特性
*/
public class MyDeferredImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"cn.tulingxueyuan.beans.Person"};
}
@Override
public Predicate<String> getExclusionFilter() {
return null;
}
@Override
public Class<? extends Group> getImportGroup() {
// 这个返回值决定调用DeferredImportSelector.selectImports 如果null
// 还是调用Group.selectImports
return MyGroup.class;
}
// 如果getImportGroup返回自定义Group , 会调用自定义Group的process方法
// 如果getImportGroup返回 null,会调用DefaultDeferredImportSelectorGroup的process方法,即调用selectImports
// 分组利用归类,同一组的bean只影响本组的顺序
private static class MyGroup
implements DeferredImportSelector.Group{
AnnotationMetadata metadata;
@Override
public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
this.metadata=metadata;
}
@Override
public Iterable<Entry> selectImports() {
List<Entry> list=new ArrayList<>();
list.add(new Entry(this.metadata,"cn.tulingxueyuan.beans.Person"));
return list;
}
}
7.源码
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
点击@SpringBootApplication
```java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
点击@EnableAutoConfiguration
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
点击@Import(AutoConfigurationImportSelector.class)
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
我们看到AutoConfigurationImportSelector实现了DeferredImportSelector
找getImportGroup,发现返回的是Group
@Override
public Class<? extends Group> getImportGroup() {
return AutoConfigurationGroup.class;
}
点击AutoConfigurationGroup,找到process
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
点击getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(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 = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
点击getCandidateConfigurations (作用获取所有的自动配置类)
获取的过程:
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;
}
点击loadFactoryNames
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
点击loadSpringFactories
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
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;
}
点击getSpringFactoriesLoaderFactoryClass( )发现,只要key为EnableAutoConfiguration的value信息
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
第11行的内容:
去除的内容类似与