巴拉巴

 找回密码
 立即注册

站内搜索

搜索
热搜: 活动 交友 discuz
查看: 92|回复: 0

Spring的启动流程探索

[复制链接]

9

主题

10

帖子

29

积分

新手上路

Rank: 1

积分
29
发表于 2023-8-17 20:17:35 | 显示全部楼层 |阅读模式
Banner printedBanner = this.printBanner(environment);就是我们熟悉的springboot工程启动的时候在控制台打印的log,我们也可以通过配置改变log的打印。
我们先介绍context = this.createApplicationContext;方法,这个方法顾名思义是创建应用上下文的,应用上下文我们都知道是用来扫描Bean的,并且种类很多。那我们spring使用了应用上下文那些去获取Bean吗,打断点进入这个方法
可以看到在这里new AnnotatedBeanDefinitionReader(this);new了一个用于读取带有注解的Bean对应的beanDefinition,还new了一个new ClassPathBeanDefinitionScanner(this);用于从路径读取Bean的BeanDefinition。
在new AnnotatedBeanDefinitionReader的时候会去调用它的构造方法,在它的构造方法里面会去将它的AnnotatedBeanDefinitionReader的BeanDefinition加入到DefaultListableBeanFactory这个类里面的beanDefinitionNames和beanDefinitionMap,这两个就是后面创建Bean必须的东西,所有Bean的注册底层都是使用的BeanDefinition。如图:
添加到DefaultListableBeanFactory这个类的beanDefinitionNames和beanDefinitionMap。
总的来说具体来说,createApplicationContext方法会根据指定的配置文件(通常是XML文件)或java配置类来创建和初始化ApplicationContext。配置文件中包含了应用程序中各种bean的定义和配置信息,Spring会根据这些信息创建出对应的bean实例,并将它们注入到相应的对象中,从而完成整个应用程序的初始化。
1context.setEnvironment(environment);这一步不用多说,就是将环境变量set到context中,设置上下文的环境。
2this.postProcessApplicationContext(context);这步操作主要是对ApplicationContext进行后置处理。那么做了哪些后置处理呢?我们点进去看下:
主要做了3部分:1.设置ApplicationContext的beanNameGenerator。2.设置ApplicationContext的ResourceLoader和ClassLoader。3.设置ApplicationContext类型转换service
3this.applyInitializers(context); 这个方法就是获取之前获取到的所有initializer类型的类,并进行初始化。
4listeners.contextPrepared(context);这个方法是通知监听器 context 准备完成;
5if (this.logStartupInfo) { this.logStartupInfo(context.getParent == null); this.logStartupProfileInfo(context); }这个代码就是打印日志,这里不做过多描述。
6ConfigurableListableBeanFactory beanFactory = context.getBeanFactory;这个方法就是获取DefaultListableBeanFactory的实例。
7beanFactory.registerSingleton(“springApplicationArguments”, applicationArguments);这步操作是注册了一个单例,单例名为“springApplicationArguments”,值为applicationArguments。
8if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}这步是判断printedBanner是否为空,如果不为空,就注册一个名为springBootBanner,值为printedBanner的单例
9if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}这个方法主要是配置bean如果重名,是否允许后一个bean覆盖前一个bean,默认是false,此时如果有同名的bean,注册到容器中,那么就会报异常。
10Set sources = this.getAllSources;获取sources列表,这里可以获取到启动类的class
11this.load(context, sources.toArray(new Object[0]));这个方法就是加载启动类,将启动类注入到容器里面。
可以看到beanDefinitionNames和beanDefinitionMap里面已经有6个了。都是主配置类。
12listeners.contextLoaded(context);这个方法我们点进去看下:
这里就是将在SpringApplciation的Initialize方法中注册的listener中属于ApplicationContextAware类型的bean都执行方法setApplicationContext,同时将这些Listener都加入到ApplicationContext中,并发布事件ApplicationPreparedEvent
这个就是刷新容器的方法
1.this.prepareRefresh,进入这个方法。
this.startupDate = System.currentTimeMillis;设置容器启动的时间
this.closed.set(false);容器的关闭标志位
this.active.set(true);将容器状态设置为有效,
this.initPropertySources;留给子类覆盖,初始化属性资源
this.getEnvironment.validateRequiredProperties;创建并获取环境对象,验证需要的属性文件是否都已经放入环境中。
最后去判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到集合中。
三,ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory这个用于获取设置容器序列化id和BeanFactory
1.this.refreshBeanFactory;,点进去看
首先使用了CAS去判断容器是否已经启动,没有启动就给beanFactory设置一个序列化id。
设置的序列化id就是你的服务名称。
2.this.getBeanFactory;,点进去看,调用了getBeanFactory方法获取了beanFactory,而beanFactory是在这个通用上下文构造方法里面就创建了的DefaultListableBeanFactory。
四,this.prepareBeanFactory(beanFactory)点进去看
这个方法就是给工厂设置必须的工具,比如el表达式解析器,资源解析器,后置处理器等。
五,this.postProcessBeanFactory(beanFactory)这个是留给子类的模板方法,允许子类对工厂执行一些处理,给Bean设置属性,单例Bean修改为多例,或者移除BeanDefinition从而避免某个Bean在spring容器中的创建。例如:
又或者用它的子类接口BeanDefinitionRegistryPostProcessor,如图
最后别忘记把这两个配置类注入到容器当中
六,this.invokeBeanFactoryPostProcessors(beanFactory)这个就是去调用Bean工厂主处理器,
java复制代码public staticvoid invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {// Invoke BeanDefinitionRegistryPostProcessors first, if any.// 将已经执行过的BeanFactoryPostProcessor存储在processedBeans,防止重复执行Set processedBeans = new HashSet;// 此处条件成立,BeanFactory类型为DefaultListableBeanFactory,而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;// 用来存放BeanFactoryPostProcessor对象List regularPostProcessors = new ArrayList;// 用来存放BeanDefinitionRegistryPostProcessor对象// 方便统一执行实现了BeanDefinitionRegistryPostProcessor接口父类的方法List registryProcessors = new ArrayList;// 处理外部定义的BeanFactoryPostProcessor,将BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor区分开for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {// 如果为BeanDefinitionRegistryPostProcessor类型if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {// 强转成BeanDefinitionRegistryPostProcessorBeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;// 如果是BeanDefinitionRegistryPostProcessor类型,直接执行postProcessBeanDefinitionRegistry方法registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);}else {// 如果不是BeanDefinitionRegistryPostProcessor类型// 则将外部集合中的BeanFactoryPostProcessor存放到regularPostProcessors用于后续一起执行regularPostProcessors.add(postProcessor);}}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!// Separate between BeanDefinitionRegistryPostProcessors that implement// PriorityOrdered, Ordered, and the rest.// 此处的currentRegistryProcessors存放当前需要执行的BeanDefinitionRegistryPostProcessorList currentRegistryProcessors = new ArrayList;// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.// TODO 首先,调用实现 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor。// 获取所有实现了BeanDefinitionRegistryPostProcessor接口的类名String postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {// 判断当前类是否实现了PriorityOrdered接口if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 将BeanDefinitionRegistryPostProcessor存入currentRegistryProcessorscurrentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 提前存放到processedBeans,避免重复执行,但是此处还未执行processedBeans.add(ppName);}}// 对currentRegistryProcessors接口中的BeanDefinitionRegistryPostProcessor进行排序,方便后续执行sortPostProcessors(currentRegistryProcessors, beanFactory);// 添加到registryProcessors集合,用于后续执行父接口的postProcessBeanFactory方法registryProcessors.addAll(currentRegistryProcessors);// 遍历集合,执行BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);// 执行完毕后,将currentRegistryProcessors清空currentRegistryProcessors.clear;// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.// TODO 接下来,调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors。// 这里为什么要再次获取BeanDefinitionRegistryPostProcessor// 是因为有可能在上面方法执行过程中添加了BeanDefinitionRegistryPostProcessor,所以这里再次获取// 而下面处理BeanFactoryPostProcessor的时候又不需要重复获取了是为什么呢?// 因为添加BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor只能在BeanDefinitionRegistryPostProcessor// 中添加,在BeanFactoryPostProcessor是无法添加的,具体看方法参数就懂了postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {// 判断当前bean没有被执行过,并且实现了Ordered接口if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {// getBean 如果BeanFactory中没有该Bean则会去创建该BeancurrentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}// 以下操作和上面是一样的,排序-->添加到registryProcessors-->执行-->清空currentRegistryProcessorssortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear;// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.// TODO 最后处理没有实现Ordered与PriorityOrdered接口的BeanDefinitionRegistryPostProcessorboolean reiterate = true;while (reiterate) {reiterate = false;// 再次获取BeanDefinitionRegistryPostProcessorpostProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (!processedBeans.contains(ppName)) {// 将本次要执行的BeanDefinitionRegistryPostProcessor存放到currentRegistryProcessorscurrentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 提前存放到processedBeans,避免重复执行processedBeans.add(ppName);reiterate = true;}}// 此处的排序已经没有意义了sortPostProcessors(currentRegistryProcessors, beanFactory);// 将本次执行的BeanDefinitionRegistryPostProcessor添加到registryProcessorsregistryProcessors.addAll(currentRegistryProcessors);// 执行invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);// 清空currentRegistryProcessors.clear;}// Now, invoke the postProcessBeanFactory callback of all processors handled so far.// TODO 现在,调用到目前为止处理的所有处理器的 postProcessBeanFactory 回调。invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// Invoke factory processors registered with the context instance.// BeanFactory如果不归属于BeanDefinitionRegistry类型,则直接执行beanFactoryPostProcessorinvokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!String postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,// Ordered, and the rest.// 用于存放实现了priorityOrdered接口的BeanFactoryPostProcessorList priorityOrderedPostProcessors = new ArrayList;// 用于存放实现了ordered接口的BeanFactoryPostProcessor名称List orderedPostProcessorNames = new ArrayList;// 用于存放无排序的BeanFactoryPostProcessor名称List nonOrderedPostProcessorNames = new ArrayList;for (String ppName : postProcessorNames) {// 如果已经执行过了,则不做处理if (processedBeans.contains(ppName)) {// skip - already processed in first phase above}// 如果实现了PriorityOrderedelse if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}// 如果实现了Orderedelse if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}// 无排序else {nonOrderedPostProcessorNames.add(ppName);}}// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.// TODO 首先,调用实现 PriorityOrdered 的 BeanFactoryPostProcessor。sortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// Next, invoke the BeanFactoryPostProcessors that implement Ordered.// TODO 接下来,调用实现 Ordered 的 BeanFactoryPostProcessors。List orderedPostProcessors = new ArrayList(orderedPostProcessorNames.size);for (String postProcessorName : orderedPostProcessorNames) {orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// Finally, invoke all other BeanFactoryPostProcessors.// TODO 最后,调用所有其他 BeanFactoryPostProcessor。List nonOrderedPostProcessors = new ArrayList(nonOrderedPostProcessorNames.size);for (String postProcessorName : nonOrderedPostProcessorNames) {nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// Clear cached merged bean definitions since the post-processors might have// modified the original metadata, e.g. replacing placeholders in values...// 清空缓存beanFactory.clearMetadataCache;}总的来说回去执行实现了BeanFactoryPostProcessor接口的类重写的方法,直接说最重要的一个子类-ConfigurationClassPostProcessor 来看看详解:
java复制代码public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List configCandidates = new ArrayList; //获取所有的BeanDefinitionName String candidateNames = registry.getBeanDefinitionNames; for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); // https://docs.spring.io/spring/docs/5.1.8.RELEASE/spring-framework-reference/core.html#beans-java-basic-concepts // Full @Configuration vs “lite” @Bean mode if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { if (logger.isDebugEnabled) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } // 校验是否为配置类 // 配置类分为两种 Full @Configuration vs “lite” @Bean mode // 校验之后在 BeanDefinition 中添加标志属性 // 如果满足条件则加入到configCandidates else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { // 如果是配置类,就放到 configCandidates 变量中 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // Return immediately if no @Configuration classes were found if (configCandidates.isEmpty) { return; } // Sort by previously determined @Order value, if applicable configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition); return Integer.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing application context SingletonBeanRegistry sbr = null; // 传入的 registry 是 DefaultListableBeanFactory if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet) { //获取自定义BeanNameGenerator,一般情况下为空 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } if (this.environment == null) { this.environment = new StandardEnvironment; } // Parse each @Configuration class // new ConfigurationClassParser,用来解析 @Configuration 类 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); // 将 configCandidates 转成 set candidates , 去重 Set candidates = new LinkedHashSet(configCandidates); Set alreadyParsed = new HashSet(configCandidates.size); do { // 解析配置类 parser.parse(candidates); parser.validate; Set configClasses = new LinkedHashSet(parser.getConfigurationClasses); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry); } // Import类,@Bean,@ImportResource 转化为 BeanDefinition this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear; // 再获取一下容器中BeanDefinition的数据,如果发现数量增加了,说明有新的BeanDefinition被注册了 if (registry.getBeanDefinitionCount > candidateNames.length) { String newCandidateNames = registry.getBeanDefinitionNames; Set oldCandidateNames = new HashSet(Arrays.asList(candidateNames)); Set alreadyParsedClasses = new HashSet; for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata.getClassName); } for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName)) { candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } while (!candidates.isEmpty); // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry); } if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { // Clear cache in externally provided MetadataReaderFactory; this is a no-op // for a shared cache since it'll be cleared by the ApplicationContext. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache; } }
点进去看一下。
再点进去。
在这里会拿到主启动类,然后再去扫描主启动类下面的Bean。
从这里进去。
这就很清晰了,去获取项目中所有使用了@Component注解Bean。
当然,这个类ConfigurationClassParser里面不止扫描使用了@Component注解的Bean。还有@Bean注解等等,如图
光是知道在哪里把使用了这些注解的Bean解析出来还不够,需要知道怎么解析出来的,就像我们学习Spring的时候那样,是通过应用上下文扫描出来的,如图
点进this.componentScanParser.parse这个方法
可以看到new ClassPathBeanDefinitionScanner,在这里new了一个应用上下文扫描,这就是原理。 而且和我们介绍context = this.createApplicationContext方法,里面构造函数创建的两个应用上下文中的一个是一样的。
至此项目中所有的Bean都被invokeBeanFactoryPostProcessors这个方法(ConfigurationClassPostProcessor最关键)解析出来。
并且通过this.reader.loadBeanDefinitions(configClasses);这个方法放到DefaultListableBeanFactory这个类里面的beanDefinitionNames和beanDefinitionMap,如图
点进去,再点进这个方法,
再点进这个方法,可以看到现在将我beanName为getgiao的Bean注册到DefaultListableBeanFactory这个类里面的beanDefinitionNames和beanDefinitionMap里面。
如图:
这个方法是将DefaultListableBeanFactory这个类里面的beanDefinitionNames和beanDefinitionMap初始化的,包括Spring三级缓存啊,这个下次再讲了。

来源:http://www.yidianzixun.com/article/0qOafLHZ
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 返回顶部