看了很多关于spring boot 的源码分析,感觉都只在关注面试题, 关键注解,但是这样并无法达到对其启动的深刻理解,只是死板的记忆,,过了几天又忘了 ,所以我在看完之后打算把他记下来,以供以后复习使用。重点是一定要自己点一遍
1. 核心注解SpringBootApplication
@SpringBootConfiguration – 配置类 就是@Configuration
@EnableAutoConfiguration – 核心注解,通过@import + @Configuration + @Bean 导入第三方jar
@ComponentScan – 包扫描,默认扫当前启动类所在包一下的所有注解 ,将其加入IOC
2. 启动类SpringApplication.run()
new SpringApplication(primarySources).run(args);
启动类Run方法可以分为两部分 new SpringApplication(primarySources) run(args);方法
@SpringBootApplication public class HelloworldApplication { public static void main(String[] args) { SpringApplication.run(HelloworldApplication.class, args); } }
进入启动类
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); this.webApplicationType = WebApplicationType.deduceFromClasspath(); this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
重点 分析三句:
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
1.1 getBootstrapRegistryInitializersFromSpringFactories()
private List<BootstrapRegistryInitializer> getBootstrapRegistryInitializersFromSpringFactories() { ArrayList<BootstrapRegistryInitializer> initializers = new ArrayList<>(); getSpringFactoriesInstances(Bootstrapper.class).stream() .map((bootstrapper) -> ((BootstrapRegistryInitializer) bootstrapper::initialize)) .forEach(initializers::add); initializers.addAll(getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); return initializers; }
核心方法: getSpringFactoriesInstances()
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {}); } private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
SpringFactoriesLoader.loadFactoryNames()
通过classloader 的双亲委派机制加载所有jar中的META-INF/spring.factories文件
并将其读取存入cache中以便下次取用。
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) { Map<String, List<String>> result = cache.get(classLoader); if (result != null) { return result; } result = new HashMap<>(); try { Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION); 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(); String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) entry.getValue()); for (String factoryImplementationName : factoryImplementationNames) { result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>()) .add(factoryImplementationName.trim()); } } } // Replace all lists with unmodifiable lists containing unique elements result.replaceAll((factoryType, implementations) -> implementations.stream().distinct() .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList))); cache.put(classLoader, result); } catch (IOException ex) { throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } return result; }
其中存储的是spring 启动中重要的类及其对应子类
在启动中接下来药用到的就是ApplicationContextInitializer 和 ApplicationListener , 最重要的还有EnableAutoConfiguration , 可以看到他又130个子类(后面再说)
当他初始化好之后,会进行一个过滤
loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
获取当前传入class的配置,当前是Bootstrapper.class , 但是在配置文件中并没有他的配置。所以instance最终为0
最后返回到最外层getBootstrapRegistryInitializersFromSpringFactories
此时bootstrapRegistryInitializers还没有值(size为0)
1.2 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
同样的逻辑,这次会取出所有ApplicationContextInitializer.class的子类
随后通过createSpringFactoriesInstances , 为所有的子类创建一个空的实例