码农翻身

《Spring源码分析》IOC的实现

- by MRyan, 2020-12-22


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

代码如下:

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信息?

<font color='red' >spring为我们定义了一个BeanDefinitionReader的统一抽象层,专门读取bean信息</front>

2. 获得了bean信息我们可以直接用反射的方式获取对象这是我们的线性思维,显然是不合理的。

<font color='red' >spring中引用了工厂模式为我们创建bean的实例,工厂类名为BeanFactory</front>

3. 对象的创建过程分为实例化分配内存,和初始化。

   <font color='red' >spring中对象的创建也不例外,除了bean的实例化还需要对属性进行填充值,当然还需要执行自定义初始方法init-method(源码中见)</front>

4. 在不同的阶段如果要做不同的操作怎么办?

   <font color='red' >spring中为我们创建了观察者模式:包括监听器,事件发布,当发布不同的事件之后,监听器接受到之后开始做相应的处理工作</front>

源码分析

启动类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。

可能源码不好理解,没关系,我画了个图,方便过下流程

在这里插入图片描述

作者:MRyan


本文采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
转载时请注明本文出处及文章链接。本文链接:https://www.wormholestack.com/archives/523/
2024 © MRyan 49 ms