百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

Spring如何加载「IOC容器」以及「装载Bean」源码解读

yuyutoo 2025-03-25 19:17 14 浏览 0 评论

SpringBoot应用开发已经非常普遍,的确,SpringBoot给我们的开发带来了很多便利,但其实,SpringBoot并没有增加什么新特性,只不过是在Spring注解的基础上做了升级版混合使用。SpringBoot的精髓就是自动装配(@EnableAutoConfiguration),我们不需要像以前使用Maven搭建项目时,引入过多的依赖包,同时还需要处理各种包冲突问题,简直是烦的要死,现在只需依赖SpringBoot核心包就能完成简单的应用开发了,所以了解Spring核心原理就非常重要了,下面我们开始从源码角度分析Spring底层原理。

下面我们首先定义一个实体类和配置类

/**
 * @Description: Dog实体类
 * @Auther: Java思享汇
 */
@Data
@ToString
public class Dog  {

    private String name;

    private Integer age;

    public Dog(){
        System.out.println("------>构造函数调用");
    }

    public void init(){
        System.out.println("------>init函数调用");
    }
}
/**
 * @Description: Configuration配置类
 * @Auther: Java思享汇
 */
@ComponentScan("com.study.spring")
@Configuration
public class DogConfiguration {

    public Dog dog(){
        return new Dog();
    }
}

接下来定一个测试类

/**
 * @Description: 测试类
 * @Auther: Java思享汇
 */
public class Test {
    @org.junit.Test
    public void test(){
        AnnotationConfigApplicationContext ac =new AnnotationConfigApplicationContext(DogConfiguration.class);
        Dog dog = (Dog) ac.getBean("dog");
        System.out.println(dog);
    }
}

我们就从
AnnotationConfigApplicationContext这个类开始,探究下Spring的IOC容器是如何装载Bean的,源码如下:

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
		this();
		register(annotatedClasses);
		//重点在下面这个方法,创建刷新容器
		refresh();
	}

然后,我们继续向下跟踪这个refresh()方法,这个方法在抽象类
AbstractApplicationContext下

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 1、刷新前的预处理
		prepareRefresh();

		// 2、获取BeanFactory
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 3、BeanFactory的预准备工作(BeanFactory进行一些设置)
		prepareBeanFactory(beanFactory);

		try {
			// 4、BeanFactory准备工作完成后进行的后置处理工作
			postProcessBeanFactory(beanFactory);

			// 5、执行BeanFactoryPostProcessor的方法
			invokeBeanFactoryPostProcessors(beanFactory);

			// 6、注册BeanPostProcessor(Bean的后置处理器),不同接口类型的BeanPostProcessor;在Bean创建前后的执行时机是不一样的
			registerBeanPostProcessors(beanFactory);

			// 7、初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
			initMessageSource();

			// 8、初始化事件派发器;
			initApplicationEventMulticaster();

			// 9、留给子容器(子类),空方法
			onRefresh();

			// 10、给容器中将所有项目里面的ApplicationListener注册进来
			registerListeners();

			// 11、重点在这,初始化所有剩下的单实例bean(自定义的单例bean)
			finishBeanFactoryInitialization(beanFactory);

			// 12、完成BeanFactory的初始化创建工作;IOC容器就创建完成
			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();
		}
	}
}

通过以上步骤,我们发现Spring的IOC容器主要完成了以下操作:

1、Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息;

  1. xml注册bean;
  2. 注解注册Bean;@Service、@Component、@Bean

2、Spring容器会合适的时机创建这些Bean

  1. 用到这个bean的时候;利用getBean创建bean;创建好以后保存在容器中;
  2. 统一创建剩下所有的bean的时候;finishBeanFactoryInitialization();

3、后置处理器;BeanPostProcessor

  1. 每一个bean创建完成,都会使用各种后置处理器进行处理;来增强bean的功能;AutowiredAnnotationBeanPostProcessor:处理自动注入AnnotationAwareAspectJAutoProxyCreator:来做AOP功能;xxx…增强的功能注解:AsyncAnnotationBeanPostProcessor…

4、事件驱动模型;

  1. ApplicationListener;事件监听;
  2. ApplicationEventMulticaster;事件派发:

接下来,我们看下装载我们自己定义的单例bean的过程,主要通过11、finishBeanFactoryInitialization(beanFactory);方法来进行处理。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// 1、判断有无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));
	}

	// 2、如果beanFactory中不包含EmbeddedValueResolver,则向其中添加一个EmbeddedValueResolver
  // EmbeddedValueResolver-->解析bean中的占位符和表达式
	if (!beanFactory.hasEmbeddedValueResolver()) {
		beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
			@Override
			public String resolveStringValue(String strVal) {
				return getEnvironment().resolvePlaceholders(strVal);
			}
		});
	}

	// 3、初始化LoadTimeWeaverAware类型的bean
  // LoadTimeWeaverAware-->加载Spring Bean时织入第三方模块,如AspectJ
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}

	// 4、释放临时类加载器
	beanFactory.setTempClassLoader(null);

	// 5、冻结缓存的BeanDefinition元数据
	beanFactory.freezeConfiguration();

	// 6、重点来了,实例化所有剩余的(非lazy init)单例(包含自定义单例bean)
	beanFactory.preInstantiateSingletons();
}

继续向下跟踪代码,6、
beanFactory.preInstantiateSingletons()位于类
DefaultListableBeanFactory下,源码如下:

@Override
public void preInstantiateSingletons() throws BeansException {
	if (this.logger.isDebugEnabled()) {
		this.logger.debug("Pre-instantiating singletons in " + this);
	}

	// 1、获取Bean的定义信息
	List beanNames = new ArrayList(this.beanDefinitionNames);
	// 2、触发初始化非懒加载单例beans
	for (String beanName : beanNames) {
		// 2.1、根据beanName获取bean的RootBeanDefinition
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
		    // 2.2、判断为FactoryBean时
			if (isFactoryBean(beanName)) {
				final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
				boolean isEagerInit;
				if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
					isEagerInit = AccessController.doPrivileged(new PrivilegedAction() {
						@Override
						public Boolean run() {
							return ((SmartFactoryBean) factory).isEagerInit();
						}
					}, getAccessControlContext());
				}
				else {
					isEagerInit = (factory instanceof SmartFactoryBean &&
							((SmartFactoryBean) factory).isEagerInit());
				}
				if (isEagerInit) {
				    // 2.2.1、重点在这,获取创建bean	
					getBean(beanName);
				}
			}
			// 非FactoryBean
			else { 
				getBean(beanName);
			}
		}
	}
   // 3、所有Bean都利用getBean创建完成以后,检查所有的Bean是否是SmartInitializingSingleton接口的;如果是;就执行afterSingletonsInstantiated();
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged(new PrivilegedAction<Object>() {
					@Override
					public Object run() {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}	

重点代码在 2.2.1、getBean(beanName);,根据beanName去获取单例bean信息,我们继续跟踪代码,位于类AbstractBeanFactory

@Override
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}

protected  T doGetBean(final String name, @Nullable final Class requiredType,	@Nullable final Object[] args, boolean typeCheckOnly)
			throws BeansException {

    // 1、转换bean的名称,去掉&前缀,且如果bean有别名的话,优先使用别名
    final String beanName = transformedBeanName(name);
    Object bean;

    // 2、从缓存中获取bean
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    // 3、如果未能从缓存中获取到bean,则要重新创建bean
    else {
        // Fail if we're already creating this bean instance: We're assumably within a circular reference.
        // 3.1判断指定的原型模式的bean是否当前正在创建(在当前线程内),如果是->则抛出异常(Spring不会解决原型模式bean的循环依赖)
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        // 3.2 检测bean definition是否存在beanFactory中
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 如果当前BeanFactory中不包含给定beanName的beanDefinition定义,且父beanFactory不为空,则去父beanFactory中再次查找
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 3.3 将name转换为原始beanName
            // 	   因为这里的name已经经过beanName的规范处理,例如:&myBean-->规范-->myBean
            // 	   所以当我们再次去父beanFactory查找时,要将beanName再次转换为原始的beanName,myBean-->回转-->&myBean
            String nameToLookup = originalBeanName(name);
            // 3.4 下面会递归调用各种getBean的方法重载,从当前bean的父factoryBean中加载bean
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // 参数不为空,则委托parentBeanFactory使用显式参数调动
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // 参数为空,则委托parentBeanFactory使用标准的getBean方法获取bean
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                // 否则委托parentBeanFactory使用默认的getBean方法
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        // 3.3 如果当前bean不是用于类型检查,则将该bean标记为已经被创建或者即将被创建
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            // 3.4 合并beanDefinition,如果指定的bean是一个子bean的话,则遍历其所有的父bean
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 校验合并的beanDefinition,如果验证失败,则抛出异常
            checkMergedBeanDefinition(mbd, beanName, args);

            // 3.5 确保初始化当前bean所依赖的bean。
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                // 循环所有的依赖bean,并递归实例化
                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 {
                        // 实例化依赖的bean
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 3.6 创建单例bean
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 创建bean
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // Explicitly remove instance from singleton cache: It might have been put there
                        // eagerly by the creation process, to allow for circular reference resolution.
                        // Also remove any beans that received a temporary reference to the bean.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            // 创建原型模式bean
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

该过程是为创建当前单例bean的准备工作。其中包括了:对BeanDefinition的检测、如果当前BeanFactory中不包含BeanDefinition则对父BeanFactory的检测、BeanDefinition的合并、依赖bean的初始化等。获取bean时,先从缓存Map中缓存中取,如果缓存中没有则到第3.6步,开始创建单例bean。好的,在以后的文章我们继续介绍Bean的创建过程

不断分享开发过程用到的技术和面试经常被问到的问题,如果您也对IT技术比较感兴趣可以「关注」我

相关推荐

ETCD 故障恢复(etc常见故障)

概述Kubernetes集群外部ETCD节点故障,导致kube-apiserver无法启动。...

在Ubuntu 16.04 LTS服务器上安装FreeRADIUS和Daloradius的方法

FreeRADIUS为AAARadiusLinux下开源解决方案,DaloRadius为图形化web管理工具。...

如何排查服务器被黑客入侵的迹象(黑客 抓取服务器数据)

---排查服务器是否被黑客入侵需要系统性地检查多个关键点,以下是一份详细的排查指南,包含具体命令、工具和应对策略:---###**一、快速初步检查**####1.**检查异常登录记录**...

使用 Fail Ban 日志分析 SSH 攻击行为

通过分析`fail2ban`日志可以识别和应对SSH暴力破解等攻击行为。以下是详细的操作流程和关键分析方法:---###**一、Fail2ban日志位置**Fail2ban的日志路径因系统配置...

《5 个实用技巧,提升你的服务器安全性,避免被黑客盯上!》

服务器的安全性至关重要,特别是在如今网络攻击频繁的情况下。如果你的服务器存在漏洞,黑客可能会利用这些漏洞进行攻击,甚至窃取数据。今天我们就来聊聊5个实用技巧,帮助你提升服务器的安全性,让你的系统更...

聊聊Spring AI Alibaba的YuQueDocumentReader

序本文主要研究一下SpringAIAlibaba的YuQueDocumentReaderYuQueDocumentReader...

Mac Docker环境,利用Canal实现MySQL同步ES

Canal的使用使用docker环境安装mysql、canal、elasticsearch,基于binlog利用canal实现mysql的数据同步到elasticsearch中,并在springboo...

RustDesk:开源远程控制工具的技术架构与全场景部署实战

一、开源远程控制领域的革新者1.1行业痛点与解决方案...

长安汽车一代CS75Plus2020款安装高德地图7.5

不用破解原车机,一代CS75Plus2020款,安装车机版高德地图7.5,有红绿灯读秒!废话不多讲,安装步骤如下:一、在拨号状态输入:在电话拨号界面,输入:*#518200#*(进入安卓设置界面,...

Zookeeper使用详解之常见操作篇(zookeeper ui)

一、Zookeeper的数据结构对于ZooKeeper而言,其存储结构类似于文件系统,也是一个树形目录服务,并通过Key-Value键值对的形式进行数据存储。其中,Key由斜线间隔的路径元素构成。对...

zk源码—4.会话的实现原理一(会话层的基本功能是什么)

大纲1.创建会话...

Zookeeper 可观测性最佳实践(zookeeper能够确保)

Zookeeper介绍ZooKeeper是一个开源的分布式协调服务,用于管理和协调分布式系统中的节点。它提供了一种高效、可靠的方式来解决分布式系统中的常见问题,如数据同步、配置管理、命名服务和集群...

服务器密码错误被锁定怎么解决(服务器密码错几次锁)

#服务器密码错误被锁定解决方案当服务器因多次密码错误导致账户被锁定时,可以按照以下步骤进行排查和解决:##一、确认锁定状态###1.检查账户锁定状态(Linux)```bash#查看账户锁定...

zk基础—4.zk实现分布式功能(分布式zk的使用)

大纲1.zk实现数据发布订阅...

《死神魂魄觉醒》卡死问题终极解决方案:从原理到实战的深度解析

在《死神魂魄觉醒》的斩魄刀交锋中,游戏卡死犹如突现的虚圈屏障,阻断玩家与尸魂界的连接。本文将从技术架构、解决方案、预防策略三个维度,深度剖析卡死问题的成因与应对之策,助力玩家突破次元壁障,畅享灵魂共鸣...

取消回复欢迎 发表评论: