Spring源码概览

源码环境搭建

关于Spring源码之前阅读过几次,只是草草的画了一些图,写了些注释,于是决定写写文字性的东西来系统一下,关于更加详细的注释,可以参考ckiss/spring-framework 5.2.x这个分支,大概是3年前陆陆续续的注释。关于源码环境的搭建可以参照网上的一些blog,出现问题的话基本上都有对应的解:

blog.csdn.net/YogaK/artic...

搭建完我们可以写一个简单的demo测试

本次阅读我采用的是5.2.9RELEASE版本。

修改gradle

可以先引入如下依赖:

python 复制代码
compile(project(":spring-beans"))
compile(project(":spring-context"))
compile("org.aspectj:aspectjrt:1.9.5")
compile("org.aspectj:aspectjweaver:1.9.5")

关于具体的代码参见: gitee.com/ckiss58/spr...

概览

ClassPathXmlApplicationContext类图解析

  • BeanFactory:是Spring框架中最基础的容器,提供了配置框架和基本功能,如获取Bean、注册Bean等。BeanFactory实现应尽可能支持标准的Bean生命周期接口。
ini 复制代码
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
MyBean myBean = (MyBean) factory.getBean("myBean");
  • HierarchicalBeanFactory:增加了对父容器的支持,可以设置和获取父容器。
ini 复制代码
HierarchicalBeanFactory childFactory = new XmlBeanFactory(new FileSystemResource("child.xml"));
childFactory.setParentBeanFactory(parentFactory);
  • ListableBeanFactory:继承自BeanFactory,增加了对所有Bean的操作,如获取所有Bean的名称、获取所有Bean的实例等。
ini 复制代码
String[] allBeanNames = listableBeanFactory.getBeanDefinitionNames();
  • ApplicationContext:继承自ListableBeanFactory和HierarchicalBeanFactory,是Spring的高级容器,除了有BeanFactory的所有功能外,还提供了更多的企业级特性,如事件发布、国际化支持、资源访问等。
ini 复制代码
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyBean myBean = (MyBean) context.getBean("myBean");

ApplicationContext继承了两个BeanFactory,而且继承了ResourcePatternResolver,故名思意,这是一个资源解析的类,所以ApplicationContext不仅是BeanFactroy,还具有资源解析的功能

java 复制代码
ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
    MessageSource, ApplicationEventPublisher, ResourcePatternResolver

Resource接口

在Spring框架中,Resource接口是一个非常重要的接口,它用于抽象底层资源的访问。Resource接口提供了一种透明的方式来访问底层资源,如文件系统、类路径、URLs等。

在传统的xml中:

ini 复制代码
<bean id="template" class="org.springframework.core.io.ClassPathResource">
    <constructor-arg value="myTemplate.txt"/>
</bean>

在Spring Boot中,Resource接口通常用于加载静态资源,如Spring Boot的application.yml或application.properties文件也可以被视为Resource,HTML、CSS、JavaScript文件等。

例如,你可以使用Resource接口来加载一个在类路径下的图片文件:

java 复制代码
@Autowired
private ResourceLoader resourceLoader;

public void loadImage() {
    Resource resource = resourceLoader.getResource("classpath:images/myImage.jpg");
    // ...
}

例如,你可以使用Resource接口来访问application.yml文件:

这样,你就可以在程序中动态地读取和修改配置信息了。

java 复制代码
@Autowired
private ResourceLoader resourceLoader;
public void loadConfig() {
    Resource resource = resourceLoader.getResource("classpath:application.yml");
    // ...
}

总的来说,Resource接口在Spring中的主要作用是提供一种统一的方式来访问底层资源,无论这些资源是在文件系统中,还是在类路径下,或者是在网络上。

  1. ClassPathResource:用于加载类路径下的资源文件。可以通过指定相对于类路径的路径来获取资源文件。
  2. FileSystemResource:用于加载文件系统中的资源文件。可以通过指定文件的绝对路径或相对路径来获取资源文件。
  3. UrlResource:用于加载网络上的资源文件。可以通过指定资源的URL来获取资源文件。
  4. ServletContextResource:用于加载Web应用程序上下文中的资源文件。可以通过指定相对于Web应用程序根目录的路径来获取资源文件。
  5. InputStreamResource:用于加载输入流中的资源。可以通过指定输入流来获取资源文件。

源码初探

看看我们的启动类

ini 复制代码
public class Main {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-test.xml");
		UserService userService = (UserService) context.getBean("userService");
		User user = userService.getUserById(1);
		System.out.println(user);
	}
}

从第一行中我们可以得出我们获取了一个ApplicationContext,那我们看看他是如何从一个xml文件获取的这个ApplicationContext

首先映入眼帘的是如下结构的代码,也就是ClassPathXmlApplicationContext的构造函数

java 复制代码
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
	this(new String[] {configLocation}, true, null);
}

public ClassPathXmlApplicationContext(
        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {
    // 这里我们传入的parent是null
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

我们来看看这个ClassPathXmlApplicationContext的构造函数的入参

  • configLocations:加载所有bean定义并创建所有singleton的资源位置数组。
  • refresh:是否自动刷新上下文,加载所有bean定义并创建所有singleton。或者,在进一步配置上下文后手动调用refresh。
  • parent:父容器

super构造函数

我们通过super分支来看看,究竟做了哪些事情

less 复制代码
public AbstractXmlApplicationContext(@Nullable ApplicationContext parent) {
	super(parent);
}
less 复制代码
public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent) {
	super(parent);
}
less 复制代码
public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
	super(parent);
}
less 复制代码
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
	this();
	setParent(parent);
}
csharp 复制代码
public AbstractApplicationContext() {
	this.resourcePatternResolver = getResourcePatternResolver();
}

通过一级一级的调用,最终到了resourcePatternResolver的初始化

这里我们回顾下AbstractApplicationContext类图:

AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext

DefaultResourceLoader implements ResourceLoader****

csharp 复制代码
protected ResourcePatternResolver getResourcePatternResolver() {
    // 这里传入this的原因是因为AbstractApplicationContext的继承体系
    return new PathMatchingResourcePatternResolver(this);
}
arduino 复制代码
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
    Assert.notNull(resourceLoader, "ResourceLoader must not be null");
    this.resourceLoader = resourceLoader;
}

我们再来看看这个PathMatchingResourcePatternResolver

java 复制代码
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
	private final ResourceLoader resourceLoader;
    private PathMatcher pathMatcher = new AntPathMatcher();
}

AntPathMatcher是Spring框架中的一个工具类,用于处理Ant风格的路径匹配。它具有以下几个作用:

  1. 路径匹配:AntPathMatcher可以根据Ant风格的路径表达式,对路径进行匹配。它支持通配符(如*和?)和路径变量(如{var}),可以方便地进行路径匹配操作。
  2. 路径匹配器:AntPathMatcher可以作为路径匹配器,用于判断一个路径是否与指定的模式匹配。它可以用于URL匹配、资源路径匹配等场景,方便地进行路径匹配判断。
  3. 路径提取:AntPathMatcher可以从一个匹配的路径中提取出路径变量的值。例如,对于模式/user/{id}和路径/user/123,AntPathMatcher可以提取出路径变量id的值为123。
  4. 路径比较:AntPathMatcher可以比较两个路径是否匹配。它可以判断一个路径是否是另一个路径的子路径,或者两个路径是否完全相同。

总之,AntPathMatcher在Spring中起着路径匹配、路径提取和路径比较等作用,方便开发者进行路径相关的操作。

setConfigLocations

接下来回到最初的代码来看setConfigLocations:

less 复制代码
public ClassPathXmlApplicationContext(
    String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
    throws BeansException {
    // 这里我们传入的parent是null
    super(parent);
    // 设置配置文件
    setConfigLocations(configLocations);
    if (refresh) {
		refresh();
	}
}

这里就是设置文件路径,具体的方法在PropertyPlaceholderHelper#parseStringValue,这个后面有空再填这个坑

核心方法refresh()

我将源码做了一定的格式化和精简,这部分代码也就是SpringIOC的核心,鼎鼎大名的容器刷新12大步 ,这一段的注释参考了www.javadoop.com/的文章

scss 复制代码
public void refresh() throws BeansException, IllegalStateException {
    // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
    synchronized (this.startupShutdownMonitor) {
        // 准备工作,记录下容器的启动时间、标记"已启动"状态、处理配置文件中的占位符
        prepareRefresh();
         // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
         // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
         // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
        // 这块待会会展开说
        prepareBeanFactory(beanFactory);
        try {
            // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
            // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】 
            // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
            // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
            postProcessBeanFactory(beanFactory);
            // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
            invokeBeanFactoryPostProcessors(beanFactory);
            // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
            // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
            // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
            registerBeanPostProcessors(beanFactory);
            // 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
            initMessageSource();
             // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
            initApplicationEventMulticaster();
            // 从方法名就可以知道,典型的模板方法(钩子方法),
            // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
            onRefresh();
        	// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
            registerListeners();
            // 初始化所有的 singleton beans (lazy-init 的除外)
            finishBeanFactoryInitialization(beanFactory);
            // 最后,广播事件,ApplicationContext 初始化完成
            finishRefresh();
        }catch (BeansException ex) {
            // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        }finally {
            resetCommonCaches();
        }
    }
}
  • 首先是synchronized对象锁,防止并发刷新容器,

接下来我们对这个模板方法的没个方法做一个简单的介绍

prepareRefresh()

按照惯例,我们先根据方法名及注释猜测这个方法是初始化上下文信息

kotlin 复制代码
	protected void prepareRefresh() {
        // 状态变更
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);
		// 在上下文环境中初始化参数占位符
		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);
		}
		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}
  1. 先看initPropertySources()
csharp 复制代码
protected void initPropertySources() {
    // For subclasses: do nothing by default.
}

这个方法中并没有任何实现逻辑,而且是 protected 修饰的,因此,这里是一个扩展点,子类可以通过重写这个方法来使用实例替换 XML 文件中的 ${} 占位符,这里只是给占位符提供一个实例作为替换内容,并未进行替换的操作,实际的替换操作在后续的流程中。

比如说,在一个子类中,重写了initPropertySources 方法,并添加了一个名叫 spring.datasource.driver-class-name 的参数的值为 com.mysql.cj.jdbc.Driver ,那么,如果在 XML 文件中出现了 ${spring.datasource.driver-class-name} ,Spring 就会将其替换为 com.mysql.cj.jdbc.Driver

  1. getEnvironment().validateRequiredProperties()

StandardEnvironment赋值给成员变量environment

csharp 复制代码
public ConfigurableEnvironment getEnvironment() {
    if (this.environment == null) {
        this.environment = createEnvironment();
    }
    return this.environment;
}

// StandardEnvironment类提供了一种标准化且方便的方式来管理和访问特定于应用程序运行环境的配置数据。
protected ConfigurableEnvironment createEnvironment() {
    return new StandardEnvironment();
}

参数校验,将参数校验的方法委托给了成员变量propertyResolver

java 复制代码
private final MutablePropertySources propertySources = new MutablePropertySources();
private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(this.propertySources);

@Override
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
   this.propertyResolver.validateRequiredProperties();
}
csharp 复制代码
// 构造方法初始化MutablePropertySources,允许AbstractEnvironment的子类操作propertySource
public AbstractEnvironment() {
    customizePropertySources(this.propertySources);
}

validateRequiredProperties的具体逻辑是

typescript 复制代码
public void validateRequiredProperties() {
    MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
    for (String key : this.requiredProperties) {
        if (this.getProperty(key) == null) {
            ex.addMissingRequiredProperty(key);
        }
    }
    if (!ex.getMissingRequiredProperties().isEmpty()) {
        throw ex;
    }
}
typescript 复制代码
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
    // 这里的propertySources是MutablePropertySources,AbstractEnvironment成员变量初始化的时候调用该方法
    if (this.propertySources != null) {
        for (PropertySource<?> propertySource : this.propertySources) {
            Object value = propertySource.getProperty(key);
            if (value != null) {
                if (resolveNestedPlaceholders && value instanceof String) {
                    value = resolveNestedPlaceholders((String) value);
                }
                logKeyFound(key, propertySource, value);
                return convertValueIfNecessary(value, targetValueType);
            }
        }
    }
    return null;
}

这里主要是通过遍历 requiredProperties 成员变量中的参数名,查看是否都有对应的值,如果有参数没有对应的值,则会报错。在 propertyResolver 被创建的时候,requiredProperties 会被初始化为一个空集合,我们可以在代码中通过调用它的 setRequiredProperties 方法,向 requiredProperties 参数名。当 Spring 容器初始化的时候,如果集合中存在找不到参数值的参数,则会报错。我们也可以利用这个特性来做容器初始化的必要参数检查。

小结:该方法设置了容器刷新状态,初始化上下文环境的参数占位符,初始化Environment,验证了必要参数和初始化一些容器早期监听器等。

obtainFreshBeanFactory()

根据方法名我们推测这个方法是获取新的BeanFactory,来看看具体实现

scss 复制代码
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}
scss 复制代码
protected final void refreshBeanFactory() throws BeansException {
    // 如果存在旧的BeanFactroy的话则关闭,创建一个新的BeanFactory
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 设置序列化id
        beanFactory.setSerializationId(getId());
        // 设置一些自定义属性
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }
}

protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

这里的getInternalParentBeanFactory()方法暂时不分析,我们后面再来填坑

我们来看看这个DefaultListableBeanFactory首先看看类图

这个DefaultListableBeanFactory几乎包含了所有的BeanFactory的功能,DefaultListableBeanFactory还有一些如下功能:

  • getBeanDefinitionNames():获取所有的BeanDefinitionName
  • getBeanNameForType() :根据类型获取beanName
  • getBean():获取Bean
  • isAllowBeanDefinitionOverriding():释放允许Bean覆盖
  • preInstantiateSingletons():初始化非懒加载Bean
kotlin 复制代码
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    if (this.allowBeanDefinitionOverriding != null) {
        beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.allowCircularReferences != null) {
        beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
}

设置是否允许BeanDefinition的覆盖,设置是否允许循环依赖

接下来是加载BeanDefinition,因为我们这里用的是XML配置文件

scss 复制代码
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // xml beanDefinition读取器
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
	// 设置一些属性
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
	// 初始化BeanDefinitionReader
    initBeanDefinitionReader(beanDefinitionReader);
    // 加载BeanDefinitions
    loadBeanDefinitions(beanDefinitionReader);
}

上面的代码前面几行都是一些属性的设置或初始化,最后一行看起来是我们需要阅读的,跟进去会来到如下的源码

csharp 复制代码
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    // 存在循环依赖的检测
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
        }
        // 这里是重点,在Spring中所有的do开头的都是逻辑的实现
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}
java 复制代码
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {
    try {
        // 加载文档,这里是XML
        Document doc = doLoadDocument(inputSource, resource);
        // 注册beanDefinition
        int count = registerBeanDefinitions(doc, resource);
        return count;
    }
}
scss 复制代码
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // 反射实例化 BeanDefinitionDocumentReader
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 注册前 BeanDefinition 的数量
    int countBefore = getRegistry().getBeanDefinitionCount();
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore;
}
scss 复制代码
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    doRegisterBeanDefinitions(doc.getDocumentElement());
}

protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        	// 检查当前环境是否接受指定的profile。如果不接受,则打印一条调试信息,并返回
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                return;
            }
        }
    }
	// 钩子函数:在解析Bean定义之前,调用preProcessXml方法对XML进行预处理
    preProcessXml(root);
	// xml解析
    parseBeanDefinitions(root, this.delegate);
	// 钩子函数:在解析Bean定义之后,调用postProcessXml方法对XML进行后置处理
    postProcessXml(root);

    this.delegate = parent;
}

小结obtainFreshBeanFactory获取bean工厂主要干了如下事情

  • 刷新bean工厂,创建了一个DefaultListableBeanFactory工厂
  • 自定义DefaultListableBeanFactory的一些属性
  • 加载BeanDefinition,并注册BeanDefintionbeanDefinitionMap,这个后面有空再解析这部分源码详见第二节

prepareBeanFactory

可以先从方法名来猜测这个方法干的事情:准备bean工厂

scss 复制代码
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    // 设置类加载器:如果没有指定类加载器,那么将使用默认的类加载器。
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置Bean表达式解析器:默认的解析器是StandardBeanExpressionResolver。 也就是SPEL解析器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    //   添加一个默认的属性编辑器。
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    // 添加aware接口的处理回调处理器- postProcessBeforeInitialization
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 将这些aware接口添加到 忽略集合
    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 interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    // 注册一些依赖
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Register early post-processor for detecting inner beans as ApplicationListeners.
    // 注册监听器,添加后置处理器:postProcessAfterInitialization
    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()));
    }

    // Register default environment beans.注册一些系统bean
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

这个方法的主要目的是为了准备BeanFactory,使其能够进行后续的bean的创建和管理。

备注:在Spring框架中,BeanPostProcessor接口是一个重要的扩展点,允许在一些关键的生命周期阶段对Bean进行自定义操作。BeanPostProcessor的实现类可以通过调用addBeanPostProcessor() 方法将其注册到Spring容器中。当我们将一个BeanPostProcessor添加到Spring容器时,它会被应用于所有在该容器中创建的bean上。这意味着每个bean都会经过该后处理器,从而影响了它们的初始化和其他生命周期回调。

在某些情况下,我们可能希望在应用BeanPostProcessor时排除特定的接口或类。这是通过调用ignoreDependencyInterface()方法来实现的。通常情况下,Spring会将这些接口视为依赖,且不需要对其进行BeanPostProcessor处理。

主要有两种情况需要使用ignoreDependencyInterface()

  1. 容器内部接口 :Spring框架本身定义了一些接口,例如ApplicationContextAwareServletContextAware等。这些接口被认为是用于提供给容器使用的,而不是作为依赖进行处理。所以,我们会将这些接口添加到ignoreDependencyInterface()中,以避免在初始化这些接口的bean时触发 BeanPostProcessor的逻辑。
  2. 非标准的AOP代理接口 :Spring的AOP功能使用代理模式进行实现,通过为bean创建动态代理对象来实现切面功能。在某些情况下,这些代理可能会实现一些框架特定的接口(例如AdvisedTargetClassAware)。由于这些接口是为了内部使用而设计的,应该被排除在BeanPostProcessor处理的范围之外。

总结:给beanfactory进行一些属性加工,设置一些BPP来满足后续对Spring bean生命周期的扩展

postProcessBeanFactory

这个是Spring提供的一个扩展点, 对BeanFactory的一些增强,来我们看看Spring源码的注释

typescript 复制代码
	/**
	 * 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.
	 * @param beanFactory the bean factory used by the application context
	 */
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

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

invokeBeanFactoryPostProcessors

关于这个方法,我想在后面单独来写一篇文章来进行解析,因为他可以给其他框架提供一些扩展点,例如我们熟知的Mybatis

finishBeanFactoryInitialization

直接来到源码概览的重点,初始化所有非懒加载的Bean

scss 复制代码
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 初始化名字为 conversionService 的 Bean
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    // 先初始化 LoadTimeWeaverAware 类型的 Bean
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);
    // Allow for caching all bean definition metadata, not expecting further changes.
    // 使Spring容器冻结,此时Spring已经预初始化了,防止此时还有bean需要注入
    beanFactory.freezeConfiguration();
    // Instantiate all remaining (non-lazy-init) singletons.
    // 初始化所有剩余的非懒加载Bean
    beanFactory.preInstantiateSingletons();
}

根据上面的代码,我们直接进入主题preInstantiateSingletons()

scss 复制代码
public void preInstantiateSingletons() throws BeansException {
    // 定义一个副本,以允许init方法注册新的beanDefinition
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        // 合并父 Bean 中的配置,也就是标签是<bean id="" class="" parent="" />
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 条件成立:说明bd是非抽象 且 是单实例 且 非懒加载,就需要预先实例化出来。
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 当前beanDefinition对应的class可能是 普通的,也可能是 FactoryBean。
            // 条件成立:说明当前bd的class是FactoryBean
            if (isFactoryBean(beanName)) {
                // 获取FactoryBean : &+beanName
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    FactoryBean<?> factory = (FactoryBean<?>) bean;
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(
                                (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                                getAccessControlContext());
                    }
                    else {
                        // 控制FactoryBean内部管理的真实bean,在refresh阶段 是否也初始化。
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }
            else {
                //@A 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了
                getBean(beanName);
            }
        }
    }

	// 触发所有的SmartInitializingSingleton bean的后置初始化回调
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

上面的一段代码就是预初始化所有的bean,重点逻辑的入口是 @A getBean(beanName) ****那一行

getBean->doGetBean
scss 复制代码
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(
        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
        throws BeansException {
    // 解析为规范的beanName
    String beanName = transformedBeanName(name);
    Object bean;

    // 检查下是不是已经创建过了
    //第一部分: 到缓存中获取共享单实例
    Object sharedInstance = getSingleton(beanName);
    // 如果args不为空,则就不是获取bean,而是创建bean
    if (sharedInstance != null && args == null) {
        // 下面这个方法:如果是普通 Bean 的话,直接返回 sharedInstance,如果是 FactoryBean 的话,返回它创建的那个实例对象
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    // 第二部分:parentBeanFactory中查找
    else {
        if (isPrototypeCurrentlyInCreation(beanName)) {
            //  创建过了此 beanName 的 prototype 类型的 bean,那么抛异常,  往往是因为陷入了循环引用
            throw new BeanCurrentlyInCreationException(beanName);
        }
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }
        if (!typeCheckOnly) {
            // 标记该beanName已创建,放入alreadyCreated 的set集合
            markBeanAsCreated(beanName);
        }
   
        try {
            // 第三部分 判断bean的依赖关系,并初始化依赖项
            // 获取合并BD信息 为什么需要合并呀?因为BD支持继承
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 判断当前BD是否为抽象BD,抽象BD不能创建实例,只能作为父BD让子BD去继承。
            checkMergedBeanDefinition(mbd, beanName, args);
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // 判断循环依赖
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        // 先初始化被依赖项
                        getBean(dep);
                    }
                }
            }

            // 第四部分:创建单例bean
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 创建Bean
                        return createBean(beanName, mbd, args);
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            // 第五部分 创建原型bean
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    // 记录当前线程相关的正在创建的原型对象beanName
                    beforePrototypeCreation(beanName);
                    // 创建
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    // 从正在创建中的集合中移除。
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
            // 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理
            else {
                // 。。。省略这部分代码
            }
        } 
    }
    // 最后,检查一下类型对不对,不对的话就抛异常,对的话就返回了
    if (requiredType != null && !requiredType.isInstance(bean)) {
         // 。。。省略这部分代码
    }
    return (T) bean;
}

我们又看到了doXXX这个关键词, 这个也就是创建bean的实际逻辑,我们将这个方法分开来分析,首先分析下这个方法的参数

name:需要获取bean的名称 name

requiredType:要获取的bean的所需类型 null

args:使用显式参数创建bean实例时要使用的参数 null

typeCheckOnly:获取实例是为了进行类型检查,而不是为了实际使用 false

第一部分
ini 复制代码
Object sharedInstance = getSingleton(beanName);
// 如果args不为空,则就不是获取bean,而是创建bean
if (sharedInstance != null && args == null) {
    // 下面这个方法:如果是普通 Bean 的话,直接返回 sharedInstance,如果是 FactoryBean 的话,返回它创建的那个实例对象
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
kotlin 复制代码
// 正在创建中的beanName集合
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 到一级缓存中获取beanName对应的单实例对象。
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 检查二级缓存
        singletonObject = this.earlySingletonObjects.get(beanName);
        // 条件成立:说明二级没有,到三级缓存查看。
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
             singletonObject = this.singletonObjects.get(beanName);
             
                if (singletonObject == null) {
                    // 再次检查二级
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    // 条件成立,则去三级创建
                    if (singletonObject == null) {
                        // 3级有数据
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            // 向2级缓存存数据
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            // 将3级缓存的数据干掉。
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}

public boolean isSingletonCurrentlyInCreation(String beanName) {
    return this.singletonsCurrentlyInCreation.contains(beanName);
}

我们通过singletonsCurrentlyInCreation这个集合的调用,可以追溯向这个集合中添加元素的源码位置

这个添加的代码如下:

typescript 复制代码
protected void beforeSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}

顺着这个思路去找,发现这个添加元素的位置在我们即将分析的第四部分中。所以第一部分的

getSingleton(beanName)的代码也就演变成了如下:

kotlin 复制代码
Object singletonObject = this.singletonObjects.get(beanName);
return singletonObject;

而这里的singletonObjects也就是我们常常谈起的Spring三级缓存中的第一级缓存,key为beanName,val为beanName对应单实例本身。所以这里返回的也就是null。

第二部分

原型bean循环依赖的检测,如果出现prototypeA -> B, B -> prototypeA,会出现如下问题:

  1. Spring会给当前线程的set中放入"A"这个BeanName
  2. 创建一个prototypeA的早期对象
  3. 这时进行属性填充的时候,返现A依赖了B类型,这时候需要通过Spring.getBean("B")来创建B
  4. 根据反射创建B的早期对象,然后再填充B的属性,发现依赖A
  5. Spring再通过getBean("A")来获取A,那么此时这个isPrototypeCurrentlyInCreation就会返回true,就会抛出异常

关于第二部分后面的内容先跳过,不是我们需要讨论的重点

第三部分
scss 复制代码
// 获取合并的bd信息
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 判断当前BD是否为抽象BD,抽象BD不能创建实例,只能作为父BD让子BD去继承。
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dep : dependsOn) {
        // 判断循环依赖
        // 假设A->B B->A
        // A第一次进来这里会返回false,会进入registerDependentBean方法
        // 此时会初始化 dependentBeanMap={A:{"B"}} dependenciesForBean={"B":{"A"}}
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        registerDependentBean(dep, beanName);
        try {
            // 先初始化被依赖项
            getBean(dep);
        }
    }
}

下面是isDependent和注册依赖bean的逻辑

typescript 复制代码
protected boolean isDependent(String beanName, String dependentBeanName) {
    synchronized (this.dependentBeanMap) {
        return isDependent(beanName, dependentBeanName, null);
    }
}

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
    if (alreadySeen != null && alreadySeen.contains(beanName)) {
        return false;
    }
    // 确定原始名称,将别名解析为规范名称
    String canonicalName = canonicalName(beanName);
    Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
    if (dependentBeans == null) {
        return false;
    }
    // 假设A已经初始化,{"A":{"B"}},现在是B的初始化,则这里的dependentBeanName=A,此时就返回true
    if (dependentBeans.contains(dependentBeanName)) {
        return true;
    }
    for (String transitiveDependency : dependentBeans) {
        if (alreadySeen == null) {
            alreadySeen = new HashSet<>();
        }
        alreadySeen.add(beanName);
        if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
            return true;
        }
    }
    return false;
}

/**
 * 为给定的bean注册一个依赖bean,在给定bean被销毁之前进行销毁。
 * @param beanName bean对应的beanName
 * @param dependentBeanName 这个bean所依赖的beanName
 */
public void registerDependentBean(String beanName, String dependentBeanName) {
    String canonicalName = canonicalName(beanName);
    // 保证map的线程安全
    synchronized (this.dependentBeanMap) {
        // 不存在则创建一个新的Set
        Set<String> dependentBeans =
                this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        // 这个beanName不存在则添加,存在则直接返回
        if (!dependentBeans.add(dependentBeanName)) {
            return;
        }
    }
    synchronized (this.dependenciesForBeanMap) {
        // 不存在则创建 dependentBeanName set
        Set<String> dependenciesForBean =
                this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
        // 添加 dependenciesForBean
        dependenciesForBean.add(canonicalName);
    }
}

根据如下的代码我们来进行一个分析:

<bean name="A" depends-on="B" ... />

<bean name="B" depends-on="A" .../>

Spring依赖两个map来发现循环依赖,一个是dependentBeanMap,一个是dependenciesForBeanMap

  1. dependentBeanMap 记录依赖当前beanName的其他beanName
  2. dependenciesForBeanMap 记录当前beanName依赖的其它beanName集合

A第一次进来这里会返回false,会进入registerDependentBean方法,此时会初始化 dependentBeanMap={A:{"B"}} dependenciesForBean={"B":{"A"}},然后走到getBean(A)的逻辑创建一个早期的Bean A,然后进入填充属性去创建B,然后就会发现isDependent方法返回true,抛出循环依赖异常

第四部分
ini 复制代码
    sharedInstance = getSingleton(beanName, () -> {
        try {
            // 创建Bean
            return createBean(beanName, mbd, args);
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

先通过getSingleton进入,注意第二个参数是一个lamda表达式,这个方法的getObject()对应的就是createBean(beanName, mbd, args);

ini 复制代码
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		synchronized (this.singletonObjects) {
            // 先从一级缓存获取
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				// 容器销毁时,会设置这个属性为true,这个时候就不能再创建bean实例了,直接抛错。
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(...);
				}
        		// 放入set集合以表示正在创建
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
                    // 这是lamda表达式,这里的getObject()也就是 return createBean(beanName, mbd, args);
					// 重点 lamda表达式的执行
                    singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					// 从正在创建bean的集合中删除
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					// 三级缓存的变更
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

来到了重点,lamda表达式的执行

scss 复制代码
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    // mbdToUse 创建实例使用 mbd.
    RootBeanDefinition mbdToUse = mbd;
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    // 条件一:拿到mbd实例化对象时的真实Class对象。
    // 条件二(!mbd.hasBeanClass()):条件成立,说明mbd在resolveBeanClass之前,是没有Class对象的。
    // 条件三:成立,说明mbd有ClassName
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides. 预处理,准备方法覆写,这里又涉及到一个概念:MethodOverrides,它来自于 bean 定义中的 <lookup-method /> 和 <replaced-method />标签
    try {
        mbdToUse.prepareMethodOverrides();
    }
    try {
        // 可以通过后处理器,在这一步返回一个代理实例对象..注意,这里的代理对象不是Spring AOP 逻辑实现的地方。
        // instantiation 实例化不要和init 搞混。
        // 后处理器调用点:创建实例之前的一个调用点。
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    try {
        // 核心方法:创建bean实例对象,并且生命周期的动作大部分都在这里
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }
}


protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 说明不是 FactoryBean,这里实例化 Bean,
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                // 后处理器调用点:合并bd信息,因为接下来就是populate处理依赖了..
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            mbd.postProcessed = true;
        }
    }

    // 循环引用
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 填充bean属性
        populateBean(beanName, mbd, instanceWrapper);
        // init-method属性 InitializingBean接口、BeanPostProcessor接口的各种回调
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    } 
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        // 条件成立:说明当前bean实例 从 2级缓存获取到了...
        // 说明产生循环依赖了...3级缓存 当前对象的ObjectFactory.getObject() 被调用过
        if (earlySingletonReference != null) {
            // 条件成立有几种情况?
            // 1.当前"真实实例"不需要被代理
            // 2.当前"实例"已经被代理过了...是在ObjectFactory.getObject() 方法调用时 实现的增强代理。
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                // 获取依赖当前bean的 其它beanName
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                // 为什么有问题?
                // 因为咱们当前对象的AOP操作是在 当前方法的 initializeBean 这个方法完成的。
                // 在这之前 外部其它bean持有到的当前的 "bean实例" 都是尚未增强的。
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(。。。 );
                }
            }
        }
    }

    try {
        // 判断当前bean实例是否需要注册 析构回调。当容器销毁时,会给当前bean的析构方法进行回调。
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    return exposedObject;
}

这段逻辑理解起来就是先实例化Bean、然后再填充Bean属性,最后执行初始化后的回调方法。 Spring源码到这里算是将IOC的核心流程过了一遍,后续有机会再看看具体流程。

相关推荐
信码由缰1 小时前
Spring框架中的Component与Bean注解
java·spring
Re2751 小时前
快速理解Spring Bean 实例化与初始化全过程
后端·spring
程序员秘密基地2 小时前
基于html,css,vue,vscode,java,springboot,mysql数据库,在线考勤,管理系统
java·vue.js·spring·html·web app
JAVA学习通4 小时前
【JavaEE进阶】图书管理系统(未完待续)
java·spring·java-ee
人生偌只如初见4 小时前
SpringAI学习笔记-MCP客户端简单示例
java·spring·ai·client·mcp
Super Rookie6 小时前
Spring Cloud 企业项目技术选型
后端·spring·spring cloud
山海上的风14 小时前
Spring Batch终极指南:原理、实战与性能优化
spring·性能优化·batch·springbatch
找不到、了16 小时前
Spring的Bean原型模式下的使用
java·spring·原型模式
超级小忍16 小时前
Spring AI ETL Pipeline使用指南
人工智能·spring
Boilermaker199219 小时前
【Java EE】SpringIoC
前端·数据库·spring