Spring源码学习---------(最简单易懂的源码学习笔记)

📢📢📢📣📣📣
哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步🤝🤝
一位上进心十足的【Java ToB端大厂领域博主】!😜😜😜
喜欢java和python,平时比较懒,能用程序解决的坚决不手动解决😜😜😜

✨ 如果有对【java】感兴趣的【小可爱】,欢迎关注我

❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️
————————————————

如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。
 

目录

前沿

读源码的方法:

温馨提示:

整体的流程

相关说明

实例化与初始化:

跟随源码debug

1、prepareRefresh方法

2、obtainFreshBeanFactory方法

3、prepareBeanFactory

4、postProcessBeanFactory(beanFactory)

5 、 invokeBeanFactoryPostProcessors(beanFactory);

6、registerBeanPostProcessors(beanFactory);

7、initMessageSource();

8、initApplicationEventMulticaster();9、onRefresh();

10、registerListeners();

11、finishBeanFactoryInitialization(beanFactory);

12、finishRefresh();


前沿

工作一段时间了,之前一直想学习一下spring的源码,最近有时间学习了一下。现在把最近学习的成果整理一下,也向大家分享一下。

下面是spring源码的学习笔记,仅供参考。本人能力有限,难免会出现问题,欢迎各位大佬指出。


读源码的方法:

之前只是看过JDK的一些源码,像是spring和springboot等源码只是简略的看过,并没有系统的学习过,同时,这么优秀的作品很是值得我们学习的。抱着好奇心开始了读spring源码的道路,废话不多说,这里把我的学习笔记分享给大家。

  1. 读源码首先找到程序的入口,例如spring的话,首先找到启动类,这里以xml的配置方法实现
  2. 读注释,注释很清楚的说明了方法和类的作用和使用方法(比我们写的要规范的多,要学习大牛们的编码风格和编码的习惯)
  3. 开始读源码的时候,不要深入细节,死抠细节,首先知道整体的过程,通过总-->分-->总的方法学习源码,这样能够提高我们读源码的效率。否则一开始就深入细节,每个方法都掌握了很容易让我们摸不到头脑,一头雾水,然后就give up了。。。这一代点我是深有体会!!
  4. 提前进行大胆的猜测,大胆的验证,之后使用debug断点调试,跟着断点走,验证之前自己的猜测,看看自己的想法和大佬们的想法有什么出路,这样能够锻炼我们的编码的思维,提升我们的编码能力和规范性。
  5. 学习整理做笔记,好记性不如烂笔头,相信读源码不做笔记的话,我门很快就会忘记的,大佬们用了很多年几经打磨才写好的程序,我门这些小白不可能三天两天就能学会的。
  6. 学会画时序图,这点很方便,能够很清楚的了解调用和引用方式。
  7. 经常查看自己的笔记,书读百遍其义自现,源码看多了我们不知不觉的就会有很大的提升
  8. 最后也是最重要的!!!!相信自己,要有信心,一定能够啃下来这些源码的,又不是让我们自己写,只是看前人的代码还看不会吗?? 不要放弃!不要放弃!不要放弃!重要的事情说三遍!!!

下面是本人的学习笔记,记得不太有条理,只是可以参考,博客的更新会把这些笔记整理一遍,不过肯定是跟不上笔记的速度的,如果有兴趣的话可以看一下,不喜勿喷。如果star一下就更好了,嘿嘿。

GitHub - ligang1006/-spring-java-: 自己的demo项目

温馨提示:

spring是非常优秀的框架,学习源码之前需要准备些基础知识,比如反射、设计模式、代理等等,这些源码本来就不是很容易学习,如果没有这些基础知识肯定会一脸懵逼的。我之前就是,上来就挑战王者(自己还是一个黑铁选手)肯定是碰的一脸灰,打击了我的学习积极性,虽然现在水平也有限,但是与之前比起来肯定是有所提升的。

好了废话不多说了,接下来就是重头戏了。


整体的流程

之前说过痛过总分总的方法学源码,下面是整个系统的工作原理,有了这些原理我们读起源码来就稍微轻松一些了(个人感觉也不那么轻松)

上面是整个spring的大致流程(细节肯定比这过要丰富很多),我们这里不拘小节,不考虑实现的细节(太多了,不可能一口吃个胖子)所以只吧主要的流程梳理过来,后面慢慢整理spring的实现细节。

1、将xml的配置加载进来,之后保存到BeanDefinition之中。

2、将Bean的定义属性通过BeanDefinitionRegister注册

3、通过BeanFactory创建对象,

4、实例化对象

5、初始化对象

spring项目启动时序图(不太标准能说明意思)

相关说明

我们在使用spring的时候,都会配置bean,这里一xml的方式实现bean的配置,所以我们猜测spring一定会有实现xml文件读取加载的过程,根据debug代理的跟随,我发现了XmlBeanDefinitionReader类,(猜测正确)实现了对xml文件的加载。

加载完成之后,Bean的定义属性信息会被存储在BeanDefinition中,那么肯定会有一个存储的方式,把这些东西存储起来,这里BeanDefinitionRegister就充当了这个角色。

BeanDefinitionRegister就像是图书馆的一个书架,存储了Bean的属性信息,供Bean的工厂使用。(也就是读者进行读书)BeanFactory和BeanDefinitionRegister直接有一个BeanFactoryPostProcessor,这个是BeanFactory的后置处理器,能够根据我们自己的需要,在spring进行初始化的时候进行增强,按照我们自己的需要增强。这里只做简单的使用。具体的使用方法,我的github笔记中有使用的例子,同样后面我也会整理BeanFactoryPostProcessor的使用方法到博客当中,尽情期待。

下面是BeanFactoryPostProcessor在项目中的简单的使用。

实例化与初始化:

实例化:只是在堆内存中开辟一份空间,并没有完成值的设置操作。

初始化:Bean在堆中分配完内存空间之后,进行赋值操作的过程。

  1. 实例化bean
  2. 应用后置处理器修改bean definition
  3. 饥饿加载单例bean,解决循环依赖问题
  4. 如何解决循环依赖问题的呢,就是提前将实例化的bean放入缓存,以beanName->bean的引用的方式放入map,在createBean的上一步getBean的时候会从缓存中先拿bean。
  5. 初始化bean实例
  6. 设置属性,如果属性是依赖注入的其他bean,走一遍getBean方法
  7. 初始化,调用aware方法、bean后置处理器的初始化前方法、初始化方法、bean后置处理器的初始化后方法
  8. 注册需要执行销毁回调的单例bean,比如在销毁方法中释放资源。

后面会单独对每一个重要的部分进行详细的介绍。


跟随源码debug

说了半天的流程和原理,接下来会跟随spring应用的启动,进行源码的讲解。

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 <bean id="a" class="net.gaven.springdemo.iocmyself.readme.springbean.A " init-method="init">
    </beans>
public class BeanTest {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        applicationContext.getBean("a");
    }
}


接下来根据断点进行调试:

public ClassPathXmlApplicationContext(
			String[] configLocations, 
boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

下面看一下注解

Create a new ClassPathXmlApplicationContext with the given parent,
loading the definitions from the given XML files.

通过加载xml文件,从给定的父环境创建一个新的xml的应用上下文环境。

这里的refresh方法是整个Spring项目启动的重中之重。

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
            //刷新前的预处理;
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
            //获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
            //BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器,BeanPostProcessor和XXXAware自动装配等)
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
                //BeanFactory准备工作完成后进行的后置处理工作(留给子类实现,空方法)
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
                //执行BeanFactoryPostProcessor的方法;
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
                //注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
                //初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
				initMessageSource();

				// Initialize event multicaster for this context.
                //初始化事件多播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
                //子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
				onRefresh();

				// Check for listener beans and register them.
                //注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
                //初始化所有剩下的非懒加载的单例bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
                //完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

refresh方法中有十来个方法,这十来个方法就是整个spring的启动过程,包括bean的生命周期管理等。(ioc的实现)

1、prepareRefresh方法

Prepare this context for refreshing, setting its startup date and 
active flag as well as performing any initialization of property sources.
protected void prepareRefresh() {
		// Switch to active.
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

  • 设置Spring容器的启动时间,
  • 开启活跃状态,撤销关闭状态,。
  • 初始化context environment(上下文环境)中的占位符属性来源。
  • 验证环境信息里一些必须存在的属性

该方法会主要做准备操作,设置初始化的数据和当任何属性资源激活后设置活动的标记。还会保存一些监听器。

2、obtainFreshBeanFactory方法

Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

该方法主要是刷新内部的工厂。实际上就是重新创建一个bean工厂,并设置工厂的一些属性。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}

这里创建的就是之前说的BeanFactory这里是ConfigurableListableBeanFactory

/**
	 * This implementation performs an actual refresh of this context's underlying
	 * bean factory, shutting down the previous bean factory (if any) and
	 * initializing a fresh bean factory for the next phase of the context's lifecycle.
	 */
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

这里主要是loadBeanDefinition方法这里是xml配置文件,所以就通过XmlBeanDefinitionReader进行Bean定义信息的读取(相当于读取材料)。之后创建BeanFactory


3、prepareBeanFactory

 Configure the factory's standard context characteristics,
such as the context's ClassLoader and post-processors.

上一步已经把工厂建好了,但是还不能投入使用,因为工厂里什么都没有,还需要配置一些东西。看看这个方法的注释。这里主要是设置刚刚创建的BeanFactory的一些属性。例如类加载器和后置处理器

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //设置BeanFactory的类加载器
        beanFactory.setBeanClassLoader(getClassLoader());
        //设置支持表达式解析器
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        //添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        //设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xx,因为ApplicationContextAwareProcessor#invokeAwareInterfaces已经把这5个接口的实现工作做了
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

        //注册可以解析的自动装配;我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
        //其他组件中可以通过 @autowired 直接注册使用
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        //添加BeanPostProcessor【ApplicationListenerDetector】后置处理器,在bean初始化前后的一些工作
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        //给BeanFactory中注册一些能用的组件;
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            //环境信息ConfigurableEnvironment
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
          //系统属性,systemProperties【Map<String, Object>】
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
          //系统环境变量systemEnvironment【Map<String, Object>】
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

4、postProcessBeanFactory(beanFactory)

Allows post-processing of the bean factory in context subclasses.

允许在上下文子类中对 bean 工厂进行后处理。  留给子类实现,空方法

看接口方法中的注解

Modify the application context's internal bean factory after its standard
initialization. All bean definitions will have been loaded, but no beans
will have been instantiated yet. This allows for registering special
 BeanPostProcessors etc in certain ApplicationContext implementations.

能够在标准的 bean 工厂 初始化之后修改内部的应用程序上下文。所有 bean 定义都将被加载,但尚未实例化任何 bean。这允许在某些 ApplicationContext 实现中注册特殊的 BeanPostProcessor 等。

这里是说 BeanFactory准备工作完成后进行的后置处理工作

上面的方法3对bean工厂进行了许多配置,现在需要对bean工厂进行一些处理。

不同的Spring容器做不同的操作。比如GenericWebApplicationContext容器的操作会在BeanFactory中添加ServletContextAwareProcessor用于处理ServletContextAware类型的bean初始化的时候调用setServletContext或者setServletConfig方法(跟ApplicationContextAwareProcessor原理一样)。

GenericWebApplicationContext#postProcessBeanFactory源码:

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        if (this.servletContext != null) {
            beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
            beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        }

        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
    }

AnnotationConfigServletWebServerApplicationContext#postProcessBeanFactory方法

@Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        super.postProcessBeanFactory(beanFactory);
        // 查看basePackages属性,如果设置了会使用ClassPathBeanDefinitionScanner去扫描basePackages包下的bean并注册
        if (this.basePackages != null && this.basePackages.length > 0) {
            this.scanner.scan(this.basePackages);
        }
        // 查看annotatedClasses属性,如果设置了会使用AnnotatedBeanDefinitionReader去注册这些bean
        if (!this.annotatedClasses.isEmpty()) {
            this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
        }
    }

5 、 invokeBeanFactoryPostProcessors(beanFactory);

Instantiate and invoke all registered BeanFactoryPostProcessor beans,
respecting explicit order if given.
<p>Must be called before singleton instantiation.

实例化并调用所有已注册的 BeanFactoryPostProcessor bean,如果给出,则遵守显式顺序。 必须在单例实例化之前调用。

	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// WARNING: Although it may appear that the body of this method can be easily
		// refactored to avoid the use of multiple loops and multiple lists, the use
		// of multiple lists and multiple passes over the names of processors is
		// intentional. We must ensure that we honor the contracts for PriorityOrdered
		// and Ordered processors. Specifically, we must NOT cause processors to be
		// instantiated (via getBean() invocations) or registered in the ApplicationContext
		// in the wrong order.
		//
		// Before submitting a pull request (PR) to change this method, please review the
		// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
		// to ensure that your proposal does not result in a breaking change:
		// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					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.
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(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.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> 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.
		List<BeanFactoryPostProcessor> 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:用来修改Spring容器中已经存在的bean的定义,使用ConfigurableListableBeanFactory对bean进行处理
  • BeanDefinitionRegistryPostProcessor:继承BeanFactoryPostProcessor,作用跟BeanFactoryPostProcessor一样,只不过是使用BeanDefinitionRegistry对bean进行处理

在Spring容器中找出实现了BeanFactoryPostProcessor接口的processor并执行。Spring容器会委托给PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法执行。


1.在springboot的web程序初始化AnnotationConfigServletWebServerApplicationContext容器时,会初始化内部属性AnnotatedBeanDefinitionReader reader,这个reader构造的时候会在BeanFactory中注册一些post processor,包括BeanPostProcessor和BeanFactoryPostProcessor(比如ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor):

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

2.在使用mybatis时,一般配置了MapperScannerConfigurer的bean,这个bean就是继承的BeanDefinitionRegistryPostProcessor,所以也是这个地方把扫描的mybatis的接口注册到容器中的。

invokeBeanFactoryPostProcessors方法处理BeanFactoryPostProcessor的逻辑如下:

从Spring容器中找出BeanDefinitionRegistryPostProcessor类型的bean(这些processor是在容器刚创建的时候通过构造AnnotatedBeanDefinitionReader的时候注册到容器中的),然后按照优先级分别执行,优先级的逻辑如下:

  1. 实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor先全部找出来,然后排序后依次执行
  2. 实现Ordered接口的BeanDefinitionRegistryPostProcessor找出来,然后排序后依次执行
  3. 没有实现PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor找出来执行并依次执行

    接下来从Spring容器内查找BeanFactoryPostProcessor接口的实现类,然后执行(如果processor已经执行过,则忽略),这里的查找规则跟上面查找BeanDefinitionRegistryPostProcessor一样,先找PriorityOrdered,然后是Ordered,最后是两者都没。

        这里需要说明的是ConfigurationClassPostProcessor这个processor是优先级最高的被执行的processor(实现了PriorityOrdered接口)。

ConfigurationClassPostProcessor会去BeanFactory中找出所有有@Configuration注解的bean,然后使用ConfigurationClassParser去解析这个类。

ConfigurationClassParser内部有个Map<ConfigurationClass, ConfigurationClass>类型的configurationClasses属性用于保存解析的类,ConfigurationClass是一个对要解析的配置类的封装,内部存储了配置类的注解信息、被@Bean注解修饰的方法、@ImportResource注解修饰的信息、ImportBeanDefinitionRegistrar等都存储在这个封装类中。

        这里ConfigurationClassPostProcessor最先被处理还有另外一个原因是如果程序中有自定义的BeanFactoryPostProcessor,那么这个PostProcessor首先得通过ConfigurationClassPostProcessor被解析出来,然后才能被Spring容器找到并执行。(ConfigurationClassPostProcessor不先执行的话,这个Processor是不会被解析的,不会被解析的话也就不会执行了)。

  1. 处理@PropertySources注解:进行一些配置信息的解析
  2. 处理@ComponentScan注解:使用ComponentScanAnnotationParser扫描basePackage下的需要解析的类(@SpringBootApplication注解也包括了@ComponentScan注解,只不过basePackages是空的,空的话会去获取当前@Configuration修饰的类所在的包),并注册到BeanFactory中(这个时候bean并没有进行实例化,而是进行了注册。具体的实例化在finishBeanFactoryInitialization方法中执行)。对于扫描出来的类,递归解析
  3. 处理@Import注解:先递归找出所有的注解,然后再过滤出只有@Import注解的类,得到@Import注解的值。比如查找@SpringBootApplication注解的@Import注解数据的话,首先发现@SpringBootApplication不是一个@Import注解,然后递归调用修饰了@SpringBootApplication的注解,发现有个@EnableAutoConfiguration注解,再次递归发现被@Import(EnableAutoConfigurationImportSelector.class)修饰,还有@AutoConfigurationPackage注解修饰,再次递归@AutoConfigurationPackage注解,发现被@Import(AutoConfigurationPackages.Registrar.class)注解修饰,所以@SpringBootApplication注解对应的@Import注解有2个,分别是@Import(AutoConfigurationPackages.Registrar.class)和@Import(EnableAutoConfigurationImportSelector.class)。找出所有的@Import注解之后,开始处理逻辑:
    1. 遍历这些@Import注解内部的属性类集合
    2. 如果这个类是个ImportSelector接口的实现类,实例化这个ImportSelector,如果这个类也是DeferredImportSelector接口的实现类,那么加入ConfigurationClassParser的deferredImportSelectors属性中让第6步处理。否则调用ImportSelector的selectImports方法得到需要Import的类,然后对这些类递归做@Import注解的处理
    3. 如果这个类是ImportBeanDefinitionRegistrar接口的实现类,设置到配置类的importBeanDefinitionRegistrars属性中
    4. 其它情况下把这个类入队到ConfigurationClassParser的importStack(队列)属性中,然后把这个类当成是@Configuration注解修饰的类递归重头开始解析这个类
  4. 处理@ImportResource注解:获取@ImportResource注解的locations属性,得到资源文件的地址信息。然后遍历这些资源文件并把它们添加到配置类的importedResources属性中
  5. 处理@Bean注解:获取被@Bean注解修饰的方法,然后添加到配置类的beanMethods属性中
  6. 处理DeferredImportSelector:处理第3步@Import注解产生的DeferredImportSelector,进行selectImports方法的调用找出需要import的类,然后再调用第3步相同的处理逻辑处理

        这里@SpringBootApplication注解被@EnableAutoConfiguration修饰,@EnableAutoConfiguration注解被@Import(EnableAutoConfigurationImportSelector.class)修饰,所以在第3步会找出这个@Import修饰的类EnableAutoConfigurationImportSelector,这个类刚好实现了DeferredImportSelector接口,接着就会在第6步被执行。第6步selectImport得到的类就是自动化配置类。

        EnableAutoConfigurationImportSelector的selectImport方法会在spring-boot-autoconfigure包的META-INF里面的spring.factories文件中找出key为org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的值,有109个,这109个就是所谓的自动化配置类(XXXAutoConfiguration)。(如果引入了mybatis和pagehelper,也会在对应的XXXautoconfigure包的META-INF里面的spring.factories找到EnableAutoConfiguration,这样可能最后得到的自动配置类会大于109个。)然后在过滤排除一下不需要的配置,最后返回实际用到的。

        ConfigurationClassParser解析完成之后,被解析出来的类会放到configurationClasses属性中。然后使用ConfigurationClassBeanDefinitionReader去解析这些类。

这个时候这些bean只是被加载到了Spring容器中。下面这段代码是ConfigurationClassBeanDefinitionReader的解析bean过程:这个时候这些bean只是被加载到了Spring容器中。下面这段代码是ConfigurationClassBeanDefinitionReader#loadBeanDefinitions的解析bean过程:

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        for (ConfigurationClass configClass : configurationModel) {
            //对每一个配置类,调用loadBeanDefinitionsForConfigurationClass方法
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
            TrackedConditionEvaluator trackedConditionEvaluator) {
        //使用条件注解判断是否需要跳过这个配置类
        if (trackedConditionEvaluator.shouldSkip(configClass)) {
            //跳过配置类的话在Spring容器中移除bean的注册
            String beanName = configClass.getBeanName();
            if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
                this.registry.removeBeanDefinition(beanName);
            }
            this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
            return;
        }

        if (configClass.isImported()) {
            //如果自身是被@Import注释所import的,注册自己
            registerBeanDefinitionForImportedConfigurationClass(configClass);
        }
        //注册方法中被@Bean注解修饰的bean
        for (BeanMethod beanMethod : configClass.getBeanMethods()) {
            loadBeanDefinitionsForBeanMethod(beanMethod);
        }
        //注册@ImportResource注解注释的资源文件中的bean
        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
        //注册@Import注解中的ImportBeanDefinitionRegistrar接口的registerBeanDefinitions
        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }

 invokeBeanFactoryPostProcessors方法总结来说就是从Spring容器中找出BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor接口的实现类并按照一定的规则顺序进行执行。 其中ConfigurationClassPostProcessor这个BeanDefinitionRegistryPostProcessor优先级最高,它会对项目中的@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理)进行解析,解析完成之后把这些bean注册到BeanFactory中。需要注意的是这个时候注册进来的bean还没有实例化。

下面这图就是对ConfigurationClassPostProcessor后置器的总结:

6、registerBeanPostProcessors(beanFactory); 准备

从Spring容器中找出的BeanPostProcessor接口的bean,并设置到BeanFactory的属性中。之后bean被实例化的时候会调用这个BeanPostProcessor。这里只是注册

        该方法委托给了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法执行。这里的过程跟invokeBeanFactoryPostProcessors类似:

  1. 先找出实现了PriorityOrdered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
  2. 找出实现了Ordered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
  3. 没有实现PriorityOrdered和Ordered接口的BeanPostProcessor加到BeanFactory的BeanPostProcessor集合中

        这些已经存在的BeanPostProcessor在postProcessBeanFactory方法中已经说明,都是由AnnotationConfigUtils的registerAnnotationConfigProcessors方法注册的。这些BeanPostProcessor包括有AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)、RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)、CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。

        如果是自定义的BeanPostProcessor,已经被ConfigurationClassPostProcessor注册到容器内。

        这些BeanPostProcessor会在这个方法内被实例化(通过调用BeanFactory的getBean方法,如果没有找到实例化的类,就会去实例化)。

7、initMessageSource();准备

国际化,applicationContext默认是支持国际化的,因为他继承了MessageSource接口所以能够实现国际化,这里不进行说明了,如有兴趣可以查询该链接,好吧有一个坑


TODO

8、initApplicationEventMulticaster();准备

在Spring容器中初始化事件广播器,事件广播器用于事件的发布。

程序首先会检查bean工厂中是否有bean的名字和这个常量(applicationEventMulticaster)相同的,如果没有则说明没有那么就使用默认的ApplicationEventMulticaster 的实现:SimpleApplicationEventMulticaster

9、onRefresh();准备

// Initialize other special beans in specific context subclasses.

一个模板方法,不同的Spring容器做不同的事情。留给子类实现

比如web程序的容器ServletWebServerApplicationContext中会调用createWebServer方法去创建内置的Servlet容器。

目前SpringBoot只支持3种内置的Servlet容器:

  • Tomcat
  • Jetty
  • Undertow


10、registerListeners(); 准备

// Check for listener beans and register them.

注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的。这不会影响到其它监听器bean。在注册完以后,还会将其前期的事件发布给相匹配的监听器。

protected void registerListeners() {
        //1、从容器中拿到所有已经创建的ApplicationListener
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            //2、将每个监听器添加到事件派发器中;
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        // 1.获取所有还没有创建的ApplicationListener
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            //2、将每个监听器添加到事件派发器中;
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // earlyApplicationEvents 中保存之前的事件,
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                //3、派发之前步骤产生的事件;
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }


11、finishBeanFactoryInitialization(beanFactory);

// Instantiate all remaining (non-lazy-init) singletons.

实例化BeanFactory中已经被注册但是未实例化的所有实例(懒加载的不需要实例化)。

比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。

实例化的过程各种BeanPostProcessor开始起作用。

后面在详细分析此步骤(又挖了一个坑)TODO

12、finishRefresh();

// Last step: publish corresponding event

refresh做完之后需要做的其他事情。

  • 初始化生命周期处理器,并设置到Spring容器中(LifecycleProcessor)
  • 调用生命周期处理器的onRefresh方法,这个方法会找出Spring容器中实现了SmartLifecycle接口的类并进行start方法的调用
  • 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作

如果是web容器ServletWebServerApplicationContext还会启动web服务和发布消息

protected void finishRefresh() {
        super.finishRefresh();
        WebServer webServer = startWebServer();
        if (webServer != null) {
            publishEvent(new ServletWebServerInitializedEvent(webServer, this));
        }
    }

好吧,终于把整个流程梳理清楚了,这是第一次系统的学习源码,这一路走过来这是不容易,跟了不知多少遍的debug调试,虽然过程很心酸但是结果很美好,给自己点一个赞👍哈哈哈,现在给自己挖了挺过的坑后面慢慢填坑。好了,spring源码的执行过程就到这了。如果有什么问题请各位大佬指出,我会很快修改的。

最后建议大家多跟源码,熟能生巧嘛

🔥课程核心价值点:

1. 一站式教学体系:涵盖编程语言基础(如Java、Python)、Web前后端开发、移动应用开发、数据结构与算法、数据库管理等多个领域,全方位构建扎实的计算机全栈知识体系;

2. 实战导向训练:依托实际项目案例,模拟企业级开发环境,让每一位学员都能亲身参与到项目实践中去,体验完整的技术研发流程;

3. 名企导师面对面:邀请来自一线互联网公司的资深工程师和项目经理担任指导老师,分享实战经验和行业动态,助力快速掌握行业规则;

4. 个性化职业规划:针对每位学员的特点提供职业发展规划建议,帮助找准定位,明晰未来发展方向;

5. 职场软技能培养:除了专业技能外,还注重团队协作、沟通表达、问题解决等职场必备素质的提升;

6. 专门的内推渠道:专项学院大厂内推渠道,内推机会多多

🎓选择我们的VIP终身会员,您将收获的不仅仅是一份简历上的硬实力,更是一次面向未来的信心之旅。让我们携手共进,在这个充满机遇与挑战的计算机世界里,一起扬帆起航,追逐星辰大海!

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智达教育‍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值