跳至主要內容

Spring IoC设计与实现

向往大约 15 分钟SpringIoc

IoC容器设计

类设计如下所示:

image-20231009154023768

  • BeanFactory:最顶层接口,提供IoC容器最基本的功能。
  • HierarchicalBeanFactory:在BeanFactory基础上提供了获取父类工厂方法。
  • ConfigurableListableBeanFactory:提供了更多bean的管理功能,包括bean注册删除等
  • ApplicationContext:面向用户使用的工厂类,提供了更多的附加功能,如支持不同的信息源、访问资源、支持应用事件等、

IoC容器的初始化过程

初始化过程包括BeanDefinition的Resource定位、加载和注入三个过程,以ClassPathXmlApplicationContext为例分析初始化过程。代码如下:

1.设置xml

<!-- applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="myBean" class="io.github.xw.model.MyBean">
        <!-- 可以设置 bean 的属性 -->
        <property name="message" value="Hello, Spring!"/>
    </bean>
</beans>

2.声明bean

public class MyBean {

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void printMessage() {
        System.out.println(message);
    }
}

3.测试

public class ClassPathXmlApplicationContextMain {
    public static void main(String[] args) {
        // 创建 ClassPathXmlApplicationContext 上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        // 获取 "myBean" 实例
        MyBean myBean = context.getBean("myBean", MyBean.class);

        // 使用 "myBean"
        myBean.printMessage();

        // 关闭上下文
        ((ClassPathXmlApplicationContext) context).close();
    }
}

resource定位过程

查看构造器逻辑,首先设置了configLocations,然后调用refresh方法,具体查看refresh方法逻辑。

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

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

关键方法实现:AbstractXmlApplicationContext#loadBeanDefinitions,该方法具体调用是在refresh方法里面,后面具体再分析。

//获取资源并定位加载	
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

image-20231009171015068

通过getConfigResourcesgetConfigLocations获取到资源后,接下来就是对资源的解析,将xml声明的数据转换成Spring的标准对象BeanDefinition,并进行载入。

BeanDefinition的加载和解析

该过程由BeanDefinitionReader实现,具体类关系图如下:

image-20231009172833024

对于ClassPathXmlApplicationContext对应的是XmlBeanDefinitionReader,关键方法如下:

	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    ....
    //通过流读取xml文件
		try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
    ...
	}

继续查看doLoadBeanDefinitions方法

	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
      //将xml配置转换成doc对象
			Document doc = doLoadDocument(inputSource, resource);
      //这里启动的是对BeanDefinition解析的详细过程,这个解析会使用到Spring的Bean
      //配置规则,是我们下面需要详细讲解的内容
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
    

查看registerBeanDefinitions方法:

	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//得到BeanDefinitionDocumentReader来对XML的BeanDefinition进行解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		//具体解析过程在这里完成,解析成BeanDefinition对象中并设置到BeanDefinitionHolder中去
    //具体流程不再分析
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

通过上述流程将xml内容解析成BeanDefinition对象,完成解析工作。

BeanDefinition注册

Bean注册逻辑在DefaultListableBeanFactory#registerBeanDefinition,实现BeanDefinitionRegistry接口

	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
    //判断同名beanName定义是否已经存在
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
      //如果存在,不允许同名的话抛出异常
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
		  .....
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
      //判断是否已经开始创建
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
        //
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				 // 把Bean的名字存入到beanDefinitionNames的同时,把beanName作为Map的key,把peanDefinition
         //作为value存入到Ioc容器持有的beanDefinitionMap中去
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
		else if (isConfigurationFrozen()) {
			clearByTypeCache();
		}
	}

完成了BeanDefinition的注册,就完成了IoC容器的初始化过程。此时,在使用的IoC容器DefaultListableBeanFactory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经可以被容器使用了,它们都在beanDefinitionMap.里被检索和使用。容器的作用就是对这些言息进行处理和维护。这些信息是容器建立依赖反转的基础。

实现一个自定义的ApplicationContext

从json文件读取简单的配置,并进行加载解析。核心代码如下:

实现一个json格式Reader读取器进行加载解析:

package io.github.xw.ioc;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.xml.sax.InputSource;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author xw
 */
public class JsonBeanDefinitionReader extends AbstractBeanDefinitionReader {
    /**
     * Create a new AbstractBeanDefinitionReader for the given bean factory.
     * <p>
     * If the passed-in bean factory does not only implement the BeanDefinitionRegistry interface but also the
     * ResourceLoader interface, it will be used as default ResourceLoader as well. This will usually be the case for
     * {@link ApplicationContext} implementations.
     * <p>
     * If given a plain BeanDefinitionRegistry, the default ResourceLoader will be a
     * {@link PathMatchingResourcePatternResolver}.
     * <p>
     * If the passed-in bean factory also implements {@link EnvironmentCapable} its environment will be used by this
     * reader. Otherwise, the reader will initialize and use a {@link StandardEnvironment}. All ApplicationContext
     * implementations are EnvironmentCapable, while normal BeanFactory implementations are not.
     *
     * @param registry
     *            the BeanFactory to load bean definitions into, in the form of a BeanDefinitionRegistry
     * @see #setResourceLoader
     * @see #setEnvironment
     */
    protected JsonBeanDefinitionReader(BeanDefinitionRegistry registry) {
        super(registry);
    }

    @Override
    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {

        try (InputStream inputStream = resource.getInputStream()) {
            //从json文件读取
            byte[] bytes = inputStream.readAllBytes();
            String content = new String(bytes);
            JsonObjectDefine jsonObjectDefine = JSON.parseObject(content, JsonObjectDefine.class);
           
            //转换成beandefinition
            AbstractBeanDefinition bd = new GenericBeanDefinition();
            bd.setResource(resource);
            bd.setDescription("");
            bd.setBeanClassName(jsonObjectDefine.getClassName());

            jsonObjectDefine.getProperties().forEach((k, v) -> {
                PropertyValue pv = new PropertyValue(k, v);
                bd.getPropertyValues().addPropertyValue(pv);
            });

           //进行注册
            BeanDefinitionHolder beanDefinitionHolder =
                new BeanDefinitionHolder(bd, jsonObjectDefine.getId(), null);
            BeanDefinitionReaderUtils.registerBeanDefinition(beanDefinitionHolder, getRegistry());

            return 1;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

声明context:

package io.github.xw.ioc;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.ResourceEntityResolver;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.AbstractRefreshableConfigApplicationContext;
import org.springframework.core.io.Resource;

import java.io.IOException;

/**
 * @author xw
 * @date 2023/10/10
 */
public class JsonApplicationContext extends AbstractRefreshableConfigApplicationContext {
    public JsonApplicationContext(String path) {
        this.setConfigLocations(path);
        refresh();
    }

    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        JsonBeanDefinitionReader beanDefinitionReader = new JsonBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        //beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        //进行加载
        loadBeanDefinitions(beanDefinitionReader);
    }

    protected void loadBeanDefinitions(JsonBeanDefinitionReader reader) throws BeansException, IOException {

        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            reader.loadBeanDefinitions(configLocations);
        }
    }
}

测试结果如下:

image-20231010115043061

IoC容器的依赖注入

bean的依赖注入核心代码在AbstractBeanFactory#doGetBean

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

    String beanName = transformedBeanName(name);
    Object beanInstance;

    // Eagerly check singleton cache for manually registered singletons.
    //先从缓存中取得Bean,处理那些已经被创建过的单件模式的Bean,对这种Bean的请求不需要
    //重复地创建
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
       if (logger.isTraceEnabled()) {
          if (isSingletonCurrentlyInCreation(beanName)) {
             logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                   "' that is not fully initialized yet - a consequence of a circular reference");
          }
          else {
             logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
          }
       }
       // 这里的getobjectForBeanInstance完成的是FactoryBean的相关处理,以取得FactoryBean的生产结果,BeanFactory和FactoryBean的区别已经在前面讲过,这个过程在后
       // 面还会详细地分析
       beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
       // Fail if we're already creating this bean instance:
       // We're assumably within a circular reference.
       if (isPrototypeCurrentlyInCreation(beanName)) {
          throw new BeanCurrentlyInCreationException(beanName);
       }
        /*这里对Ioc容器中的BeanDefintion是否存在进行检查,检查是否能在当前的BeanFactory中取
得需要的Bean。如果在当前的工厂中取不到,则到双亲BeanFactory中去取,如果当前的双亲工
厂取不到,那就顺着双亲BeanFactory链一直向上查找*/
       // Check if bean definition exists in this factory.
       BeanFactory parentBeanFactory = getParentBeanFactory();
       if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
          // Not found -> check parent.
          String nameToLookup = originalBeanName(name);
          if (parentBeanFactory instanceof AbstractBeanFactory) {
             return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                   nameToLookup, requiredType, args, typeCheckOnly);
          }
          else if (args != null) {
             // Delegation to parent with explicit args.
             return (T) parentBeanFactory.getBean(nameToLookup, args);
          }
          else if (requiredType != null) {
             // No args -> delegate to standard getBean method.
             return parentBeanFactory.getBean(nameToLookup, requiredType);
          }
          else {
             return (T) parentBeanFactory.getBean(nameToLookup);
          }
       }

       if (!typeCheckOnly) {
          markBeanAsCreated(beanName);
       }

       StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
             .tag("beanName", name);
       try {
          if (requiredType != null) {
             beanCreation.tag("beanType", requiredType::toString);
          }
          //根据bean的名字获取BeanDefinition
          RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
          checkMergedBeanDefinition(mbd, beanName, args);

          // Guarantee initialization of beans that the current bean depends on.
          //获取当前Bean的所有依赖Bean,这样会触发getBean的递归调用,直到取到一个没有
          //任何依赖的Bean为止
          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);
                }
                catch (NoSuchBeanDefinitionException ex) {
                   throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                         "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                }
             }
          }
          /*这里通过调用createBean方法创建singleton bean的实例,这里有一个回调函数
getobject,会在getsingleton中调用objectFactory的createBean*/
          // Create bean instance.
          if (mbd.isSingleton()) {
             sharedInstance = getSingleton(beanName, () -> {
                try {
                   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;
                }
             });
             beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
          }
          //创建prototype 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);
             }
             beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
          }

          else {
             String scopeName = mbd.getScope();
             if (!StringUtils.hasLength(scopeName)) {
                throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
             }
             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);
                   }
                });
                beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
             }
             catch (IllegalStateException ex) {
                throw new ScopeNotActiveException(beanName, scopeName, ex);
             }
          }
       }
       catch (BeansException ex) {
          beanCreation.tag("exception", ex.getClass().toString());
          beanCreation.tag("message", String.valueOf(ex.getMessage()));
          cleanupAfterBeanCreationFailure(beanName);
          throw ex;
       }
       finally {
          beanCreation.end();
       }
    }

    return adaptBeanInstance(name, beanInstance, requiredType);
}

插件具体的实现方法AbstractAutowireCapableBeanFactory#doCreateBean,调用链路如下图所示

image-20231010150223029

代码如下:

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

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    //如果是单例bean,先把缓存中的同名bean清除
    if (mbd.isSingleton()) {
       instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
       instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
       mbd.resolvedTargetType = beanType;
    }
....
    // Initialize the bean instance.
    //对bean进行初始化,在这里进行依赖注入。
    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);
       }
    }

    if (earlySingletonExposure) {
       Object earlySingletonReference = getSingleton(beanName, false);
       if (earlySingletonReference != null) {
          if (exposedObject == bean) {
             exposedObject = earlySingletonReference;
          }
          else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
             String[] dependentBeans = getDependentBeans(beanName);
             Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
             for (String dependentBean : dependentBeans) {
                if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                   actualDependentBeans.add(dependentBean);
                }
             }
             if (!actualDependentBeans.isEmpty()) {
                throw new BeanCurrentlyInCreationException(beanName,
                      "Bean with name '" + beanName + "' has been injected into other beans [" +
                      StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                      "] in its raw version as part of a circular reference, but has eventually been " +
                      "wrapped. This means that said other beans do not use the final version of the " +
                      "bean. This is often the result of over-eager type matching - consider using " +
                      "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
             }
          }
       }
    }

    // Register bean as disposable.
    try {
       registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
       throw new BeanCreationException(
             mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

在这里有createBeanInstancepopulateBean两个方法与依赖注入关系比较密切。

createBeanInstance方法主要完成bean的实例化。代码如下:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    //确保需要创建的Bean实例的类可以实例化
    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);
    }

    // Preferred constructors for default construction?
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
       return autowireConstructor(beanName, mbd, ctors, null);
    }

    // No special handling: simply use no-arg constructor.
    //无参构造器初始,用CGLIB对Bean进行实例化,在CglibSubclassingInstantiationStrategy中可以看到具体的实例化过程
    return instantiateBean(beanName, mbd);
}

populateBean负责处理实例化对象之间的依赖关系,完成整个依赖注入的过程。代码如下:

	@SuppressWarnings("deprecation")  // for postProcessPropertyValues
	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
     ....
     //开始进行依赖注入过程,先处理autowaire注入  
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
      //根据名字注入
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
      //根据类型注入
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
....
		if (pvs != null) {
       //进行属性注入,不再具体分析
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

补充说明:

AUTOWIRE_BY_NAME:Spring容器会根据属性的名称来查找匹配的依赖对象。它要求属性的名称与要注入的依赖对象的bean名称相匹配。如果找到匹配的bean名称,Spring容器将注入该对象

AUTOWIRE_BY_TYPE:Spring容器会根据属性的类型来查找匹配的依赖对象。它要求属性的类型与要注入的依赖对象的bean类型相匹配。如果找到匹配的bean类型,Spring容器将注入该对象。

至此已经完成了对各种Bean属性的依赖注入过程。在Bean的创建和对象注入的过程中,依据BeanDefinition中的信息来递归完成依赖注入,在对Bean的属性进行依赖注入时,解析的过程是一个递归的过程。这样,根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这
个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。这里会存在一个问题,那就是循环依赖,如果存在这样的依赖关系,如A->B,B->C,C->A,Spring IoC又是怎么去处理的呢?

设计一个循环依赖的例子,代码如下:

public class ClassA {
    private ClassB classB;

    public void setClassB(ClassB classB) {
        this.classB = classB;
    }

    public void doSomethingA() {
        System.out.println("ClassA is doing something.");
        classB.doSomethingB();
    }
}

public class ClassB {
    private ClassC classC;

    public void setClassC(ClassC classC) {
        this.classC = classC;
    }

    public void doSomethingB() {
        System.out.println("ClassB is doing something.");
        classC.doSomethingC();
    }
}

public class ClassC {
    private ClassA classA;

    public void setClassA(ClassA classA) {
        this.classA = classA;
    }

    public void doSomethingC() {
        System.out.println("ClassC is doing something.");
       
    }
}

Spring通过三级缓存来解决循环依赖。

	//org.springframework.beans.factory.support.DefaultSingletonBeanRegistry

  //一级缓存,存储的是spring初始好的对象
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
  //三级缓存。缓存的是对象工厂
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
  //二级缓存。存储的是早期的单例对象,仅仅实例化好了,但是没有进行初始化
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

对于上述A B C实例的初始化过程如下所示:

image-20231010190736255

通过三级缓存就解决bean的循环依赖问题,其实只需要二级缓存就能处理循环依赖,引入三级缓存的目的是为了解决代理对象的循环依赖。首先查看bean的声明周期及初始化过程。

image-20231010192640400

首先明白一个点,只有BeanPostProcessors后置处理完成后才认为一个bean真正初始化完成。spring Aop的代理对象也是通过BeanPostProcessor` 来完成的,为AnnotationAwareAspectAutoProxyCreator,为了尽可能的延缓 BeanPostProcessor 的调用,Spring 才采用了三级缓存,存入一个 Objectactory 对象,并不创建,而是当发生了循环依赖的时候,采取三级缓存获取到三级缓存来创建对象,因为发生了循环依赖的时候,不得不提前调用 BeanPostProcessor 来完成实例的初始化。

Bean生命周期

  1. BeanNameAware's setBeanName:设置beanName
  2. BeanClassLoaderAware's setBeanClassLoader:设置类加载器
  3. BeanFactoryAware's setBeanFactory:将当前的 BeanFactory(Spring 容器)传递给该 bean
  4. EnvironmentAware's setEnvironment:设置环境变量
  5. EmbeddedValueResolverAware's setEmbeddedValueResolver:是 Spring 框架中的一个接口,用于支持解析占位符表达式(Placeholder Expression)的功能。
  6. ResourceLoaderAware's setResourceLoader (only applicable when running in an application context):将 ResourceLoader 对象注入到实现了该接口的 bean 中
  7. ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context):将 ApplicationEventPublisher 注入到实现了该接口的 bean 中
  8. MessageSourceAware's setMessageSource (only applicable when running in an application context):设置消息源
  9. ApplicationContextAware's setApplicationContext (only applicable when running in an application context):设置上下文
  10. ServletContextAware's setServletContext (only applicable when running in a web application context):设置servlet上下文
  11. postProcessBeforeInitialization methods of BeanPostProcessors:前置处理
  12. InitializingBean's afterPropertiesSet:设置完属性后调用
  13. a custom init-method definition:执行自定义的初始方法
  14. postProcessAfterInitialization methods of BeanPostProcessors 后置处理

在Bean的初始化过程中,内置了很多扩展方式支持用户对bean进行扩展,笔者写了一个小示例:

public class MyBean implements EmbeddedValueResolverAware, InitializingBean {

    private StringValueResolver embeddedValueResolver;

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void printMessage() {
        System.out.println(message);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("EmbeddedValueResolverAware.setEmbeddedValueResolver方法");
        this.embeddedValueResolver=resolver;
        String resolvedValue = embeddedValueResolver.resolveStringValue("${my.property}");

    }
    
    public void customMethodInit(){
        System.out.println("自定义方法调用");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet");
        System.out.println(this.message);
    }
}

自定义Bean后置处理器:

public class CustomBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor前置处理");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor后置处理");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

配置xml:

<!-- applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="myBean" class="io.github.xw.model.MyBean" init-method="customMethodInit">
        <!-- 可以设置 bean 的属性 -->
        <property name="message" value="Hello, Spring!"/>
    </bean>


    <bean id="customBeanPostProcessor" class="io.github.xw.ioc.lifecycle.CustomBeanPostProcessor" >
    </bean>
</beans>

结果如下:

image-20231011145031400

总结

Spring内置了很多的实现将不同来源的bean定义转成BeanDefinition,在Bean的创建和对象依赖注入的过程中,需要依据BeanDefinition中的信息来递归地完
成依赖注入。从上面的几个递归过程中可以看到,这些递归都是以getBean为入口的。一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用,另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注人。在对Bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。

参考资料:

  • 《Spring技术内幕》

源码地址