《Spring源码分析》IOC的实现

232 阅读9分钟

由一个简单的例子引出本文

代码如下: user.java

@Data
public class User {

    private String username;

    private int id;
}

userbean.xml

<?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 name="user" class="com.mryan.springcore.demo.User">
        <property name="username" value="MRyan"></property>
        <property name="id" value="666"></property>
    </bean>
</beans>

启动类,并实现了ApplicationRunner方法

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {


    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    
    @Override
    public void run(String... args) throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml");
        User user = (User) context.getBean("user");
        System.out.println(user.toString());
    }
}

xml配置文件向spring ioc容器中注册一个bean,并运行程序打印bean信息。 在这里插入图片描述 成功打印结果。

我们会发现貌似我们什么都不用知道,spring框架都替我们想到了,我们几乎不用做什么,spring框架替我们做了,那么问题来了,它是怎么做到的呢?对象到底是怎么创建的呢?

在阅读源码之前我们先补一下知识

知识小课堂

  1. 我们可以用XML,配置类,注解等方式来定义bean信息,容器会读取bean信息,那容器如何能兼容读取这些不同方式定义的bean信息? spring为我们定义了一个BeanDefinitionReader的统一抽象层,专门读取bean信息

  2. 获得了bean信息我们可以直接用反射的方式获取对象这是我们的线性思维,显然是不合理的。 spring中引用了工厂模式为我们创建bean的实例,工厂类名为BeanFactory

  3. 对象的创建过程分为实例化分配内存,和初始化。 spring中对象的创建也不例外,除了bean的实例化还需要对属性进行填充值,当然还需要执行自定义初始方法init-method(源码中见)

  4. 在不同的阶段如果要做不同的操作怎么办? spring中为我们创建了观察者模式:包括监听器,事件发布,当发布不同的事件之后,监听器接受到之后开始做相应的处理工作

源码分析

启动类ApplicationContext 处打断点一步一步调试

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {


    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml");//断点处
        User user = (User) context.getBean("user");
        System.out.println(user.toString());
    }
}

进入ClassPathXmlApplicationContext中

	public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
		this(new String[] {configLocation}, true, null);
	}
public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
        //使用给定的父上下文创建一个新的AbstractXmlApplicationContext
		super(parent);
		//设置此应用程序上下文的配置位置
		setConfigLocations(configLocations);
		if (refresh) {
		   //核心
			refresh();
		}
	}

继续debug进入refresh方法,下面对于一些非核心的方法选择性跳过,只分析核心代码,对于refresh方法也可以看之前我写的文章《SpringBoot源码分析》 Context初始化流程


	@Override
	public void refresh() throws BeansException, IllegalStateException {
		//1 加锁,确保了同一时间startupShutdownMonitor的状态不发生改变。
		synchronized (this.startupShutdownMonitor) {
			//2 为刷新做准备 设置启动日期和活跃状态等
			prepareRefresh();
			//3 ****核心**** 
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			//4 准备BeanFactory 各种设置 各种register这里不做叙述
			prepareBeanFactory(beanFactory);

			try {
				//5 ****核心**** 
				postProcessBeanFactory(beanFactory);

				//6 执行BeanFactoryPostProcessors 实例化并且执行已经注册了的BeanFactoryPostProcessors
				invokeBeanFactoryPostProcessors(beanFactory);

				//7 实例化并且注册所有BeanPostProcessor的Beans
				registerBeanPostProcessors(beanFactory);

				//8 国际化配置
				initMessageSource();

				//9 初始化应用事件广播器。事件广播器用来向 ApplicationListener 通知各种应用产生的事件,是一个标准的观察者模式。
				initApplicationEventMulticaster();

				//10 是留给子类的扩展步骤,用来让特定的 Context 子类初始化其他的 Bean。
				onRefresh();

				//11 把实现了 ApplicationListener 的 Bean 注册到事件广播器,并对广播器中的早期未广播事件进行通知。观察者模式:包括监听器,事件发布,当发布不同的事件之后,监听器接受到之后开始做相应的处理工作
				registerListeners();

				// 12 ****核心**** 
				finishBeanFactoryInitialization(beanFactory);

				// 13 完成上下文的刷新工作,调用 LifecycleProcessor 的 onFresh() 方法以及发布 ContextRefreshedEvent 事件。
				finishRefresh();
			}

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


				destroyBeans();

				cancelRefresh(ex);

				throw ex;
			}

			finally {
				//14
				resetCommonCaches();
			}
		}
	}

在3处 根据代码命名我们很容易猜到obtainFreshBeanFactory方法作用是获取BeanFactory,并加载bean定义信息 进入方法

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//判断当前容器中是否由BeanFactory,如果由就销毁,没有则创建
		refreshBeanFactory();
		//返回BeanFactory
		return getBeanFactory();
	}

进入refreshBeanFactory方法

@Override
	protected final void refreshBeanFactory() throws BeansException {
	   //判断当前的beanFactory是否为空,不为空则证明当前容器中存在BeanFactory进行销毁,否则创建BeanFactory
		if (hasBeanFactory()) {//	return (this.beanFactory != null);
			destroyBeans();
			closeBeanFactory();
		}
		try {
		   //创建BeanFactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			//设置序列号ID
			beanFactory.setSerializationId(getId());
			//自定义BeanFactory
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

可以发现此时beanDefiinitionMap中就存在了之前定义的bean信息在这里插入图片描述

在5处: 进入postProcessBeanFactory方法

	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

空的方法,这其实是Spring为我们提供让我们自行扩展的方法,在上面我们获取了BeanDefinition,在放入BeanFactory之前我们可以对bean信息进行修改等操作,我们就可以实现BeanFactoryPostProcessor并重写postProcessBeanFactory方法在其中添加逻辑代码。

在第12处开始 就进入最最最核心的地方。 进入finishBeanFactoryInitialization内部

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 为此上下文初始化转换服务。
		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));
		}

		// 如果之前没有任何bean后处理器(例如,PropertyPlaceholderConfigurer Bean)进行注册,请注册默认的嵌入式值解析器:此时,主要用于解析注释属性值。
		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);
		}

		// 停止使用临时ClassLoader进行类型匹配。
		beanFactory.setTempClassLoader(null);

		// 允许缓存所有bean定义元数据,而不期望进一步的更改。
		beanFactory.freezeConfiguration();

		// ****核心**** 实例化所有剩余的(非延迟初始化)单例。
		beanFactory.preInstantiateSingletons();
	}

我们可以看到最后一行标注核心的代码,我们继续进入方法

@Override
	public void preInstantiateSingletons() throws BeansException {
		****省略之前
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
		// 触发所有非惰性单例bean的初始化...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//如果它不是抽象的并且是单例是懒加载的才进入此判断语句
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			//如果FactoryBean中存在该beanName走此判断语句
				if (isFactoryBean(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 {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				//以上不符合条件 显然跳到了这里
				else {
					getBean(beanName);
				}
			}
		}

		***省略之后

首先核心代码处for循环,从beanDefinitionNames中获取BeanName,显而易见本例中只有一个beanName=user 在这里插入图片描述

进入getBean方法

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

在进入doGetBean方法

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

	***省略以上代码

				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
						//断点
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
						
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

			***省略以下代码
		

如果是单例的话进入判断,进入createBean方法 此时完成对bean的创建

	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

      ***省略以上代码
		try {
		//doCreateBean 实际创建指定的bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

进入doCreateBean方法 此时才进行Bean的实例化


protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// 实例化bean
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
		//*****核心*****  使用适当的实例化策略为指定的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 {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

	
		

来看看createBeanInstance做了什么吧 使用适当的实例化策略为指定的bean创建一个新实例,


protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		//默认构造的首选构造函数  案例中没有给定构造器
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		//无需特殊处理:只需使用no-arg构造函数
		return instantiateBean(beanName, mbd);
	}

上述流程进入到instantiateBean方法 此时才会使用其默认构造函数实例化给定的bean

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged(
				//核心 在此工厂中以给定名称返回Bean的实例		
						(PrivilegedAction<Object>) () -> 
				getInstantiationStrategy().instantiate(mbd, beanName, this),
						getAccessControlContext());
			}
			else {
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

进入instantiate方法中 此时在此工厂中以给定名称返回Bean的实例,并且过程中调用ctor.newInstance(argsWithDefaultValues); 完成了实例化

@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							constructorToUse = clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			//此处执行ctor.newInstance(argsWithDefaultValues); 真正的完成对象的实例化
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

继续step over结果逐层返回直到到AbstractAutowireCapableBeanFactory类的doCreateBean方法 在这里插入图片描述 可以看到当前bean对象已经被实例化出来了,但是还没有设置属性值。

下方有段核心代码

//填充bean 其实就是填充属性值
populateBean(beanName, mbd, instanceWrapper);

结果逐层返回,我们发现属性值填充成功 在这里插入图片描述

接着流程走到initializeBean方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
		//BeanPostProcessor(前置方法)
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
		//bean初始化用户自定义初始方法init-method
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
		//BeanPostProcessor(后置方法)
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

到此为止完成了bean对象的读取,创建,实例化,执行用户自定义初始方法init-method。

可能源码不好理解,没关系,我画了个图,方便过下流程 在这里插入图片描述