Spring源码之IOC

2. IOC

核心概念:

  • 控制反转
  • 依赖注入

本节主要针对 BeanFactory 分析

2.1 测试样例

分析源码之前,需要有测试用例。在spring-context项目中,依次新建:

  • org.springframework.demo.Dog.java
  • org.springframework.demo.DogTests.java
  • resources/org/springframework/demo/demo.xml
package org.springframework.demo;

public class Dog {
	private String name;
	private int age;

	public Dog() {
	}

	public Dog(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public void sayHello() {
		System.out.println("大家好, 我叫" + getName() + ", 我今年" + getAge() + "岁了");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}
<?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
	   https://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="dog" class="org.springframework.demo.Dog">
		<property name="name" value="Jack"/>
		<property name="age" value="12"/>
	</bean>
</beans>
package org.springframework.demo;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class DogTests {

	@Test
	public void dogBean() {
		XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("org/springframework/demo/demo.xml"));
		Dog dog = xmlBeanFactory.getBean("dog", Dog.class);
		dog.sayHello();
	}
}

2.2 从缓存中获取bean实例

  • Spring Bean的作用域有:
    • prototype
    • singleton 本专栏主要针对 singleton 分析
    • request
    • session
    • global session
  • 针对单例bean,IOC会缓存bean的实例信息,在doGetBean方法中有:
// 从缓存中获取bean实例
Object sharedInstance = getSingleton(beanName);
  • 单例bean的实例信息被缓存在了:
// 缓存bean的实例信息
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  • 获取单例bean实例的部分代码(涉及循环依赖部分后文分析,初学者不要过度解读每一行代码):
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// 从缓存中获取实例
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
	   // 省略部分代码。。。
	}
	return singletonObject;
}
  • 总结:
    • 针对单例bean,IOC先从缓存中获取该bean的实例,即从ConcurrentHashMap中获取。
    • beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); 这里涉及到FactoryBean相关知识,放到后续章节分析。

2.3 实例化bean的准备工作

接上文,Spring 首先尝试从缓存中获取bean的实例,若未能获取到,则创建新的bean的实例:

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

方法大体分为四个步骤,内部逻辑十分复杂,但是需要现有整体上的了解:

  • getSingleton 获取单例bean实例
  • createBean 创建bean实例
  • catch 异常处理
  • getObjectForBeanInstance(涉及FactoryBean,后续分析)
2.3.1 getSingleton

抛开创建bean实例来看,该方法主要处理创建bean的前置、后置、缓存等工作。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	// 加锁
	synchronized (this.singletonObjects) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			if (this.singletonsCurrentlyInDestruction) {
				throw new BeanCreationNotAllowedException(beanName,
						"Singleton bean creation not allowed while singletons of this factory are in destruction " +
						"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
			}
			// 在单例创建之前回调。
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			try {
				// 创建bean实例
				singletonObject = singletonFactory.getObject();
				newSingleton = true;
			}
			catch (IllegalStateException ex) {
				// Has the singleton object implicitly appeared in the meantime ->
				// if yes, proceed with it since the exception indicates that state.
				// 在此期间是否隐式地出现了单例对象——>如果是,则继续处理它,因为异常指示了该状态。
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					throw ex;
				}
			}
			catch (BeanCreationException ex) {
				if (recordSuppressedExceptions) {
					for (Exception suppressedException : this.suppressedExceptions) {
						ex.addRelatedCause(suppressedException);
					}
				}
				throw ex;
			}
			finally {
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = null;
				}
				// 在单例创建后回调。
				afterSingletonCreation(beanName);
			}
			if (newSingleton) {
				// 缓存bean实例
				addSingleton(beanName, singletonObject);
			}
		}
		return singletonObject;
	}
}
  • 前置回调 --> beforeSingletonCreation
  • 创建bean实例 --> singletonFactory.getObject(); (代码太多,本小节不分析
  • 异常处理
  • 后置回调 --> afterSingletonCreation
  • 缓存实例 --> addSingleton
2.3.1.1 beforeSingletonCreation 前置处理
protected void beforeSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
		throw new BeanCurrentlyInCreationException(beanName);
	}
}
  • 重要变量:
    • 当前在创建检查中排除的bean的名称:inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    • 标记bean是否正在创建中:singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
  • 逻辑:检查循环依赖,如果当前bean已经被标记为正在创建中,则抛出BeanCurrentlyInCreationException
2.3.1.2 afterSingletonCreation 后置处理
protected void afterSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
		throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
	}
}
  • 逻辑:与 beforeSingletonCreation 相反,因为bean已经创建完成,需要从 singletonsCurrentlyInCreation 移除
2.3.1.3 addSingleton 缓存bean实例
protected void addSingleton(String beanName, Object singletonObject) {
	// 加锁
	synchronized (this.singletonObjects) {
		// 单例对象的缓存:从bean名称到bean实例。
		this.singletonObjects.put(beanName, singletonObject);
		// 单例工厂的缓存:从bean名到ObjectFactory。
		this.singletonFactories.remove(beanName);
		// 早期单例对象的缓存:从bean名称到bean实例。
		this.earlySingletonObjects.remove(beanName);
		// 一组已注册的单例,包含按注册顺序排列的bean名称。
		this.registeredSingletons.add(beanName);
	}
}
  • 变量定义:
    • private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    • private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    • private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
    • private final Set registeredSingletons = new LinkedHashSet<>(256);
  • 主要逻辑
    • 将创建的Bean实例加入到 ConcurrentHashMap 中
    • 如果刚开始看Spring源码,只需要理解 singletonObjects 即可。
2.3.2 createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;
	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.
	// 确保此时实际解析了bean类,并在无法存储在共享合并bean定义中的动态解析类的情况下克隆bean定义。
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}
	// Prepare method overrides.
	// 准备方法覆盖。
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}
	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		// 让BeanPostProcessors有机会返回一个代理而不是目标bean实例。
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}
	try {
		// 创建bean实例
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		// A previously detected exception with proper bean creation context already,
		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}
  • 主要方法与变量:
    • RootBeanDefinition Bean定义
    • resolveBeanClass 解析BeanClass
    • prepareMethodOverrides 准备方法覆盖。
    • resolveBeforeInstantiation 让BeanPostProcessors有机会返回一个代理而不是目标bean实例。
    • doCreateBean 真正开始创建bean实例
    • 异常处理
  • 逻辑:该方法依然是做创建Bean的准备工作
  • resolveBeforeInstantiation涉及到AOP相关,放到后续小节分析,下面我们简单介绍下RootBeanDefinition、和prepareMethodOverrides
2.3.1 RootBeanDefinition 简介

关于 RootBeanDefinition 前文已经出现过,为了快速入门,并没有对其做过多介绍,这里我们简单了解一下:

  • 将Bean的定义信息转化为Spring的内部表示。
  • 间接实现了 BeanDefinition 接口,BeanDefinition 描述bean实例,该实例具有属性值、构造函数参数值和具体实现提供的进一步信息。
2.3.2 prepareMethodOverrides

**注意:这里的 method overrides 指方法注入。**该部分对应的源码比较简单,掌握其基本使用,应该都能读懂。下面演示一下lookup-method、replace-method的使用:

  • 新建 BaseTests,为了方便测试,需要一个测试基类。
  • lookup-method 依次新建
    • org.springframework.demo.method.lookup.Car
    • org.springframework.demo.method.lookup.Taxi
    • org.springframework.demo.method.lookup.LookUpTests
  • replace-method 依次新建
    • org.springframework.demo.method.replace.OriginalDog
    • org.springframework.demo.method.replace.ReplaceDog
    • org.springframework.demo.method.replace.ReplaceTests
  • 代码
-- for BaseTests
package org.springframework.demo;

import org.junit.jupiter.api.BeforeAll;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class BaseTests {

	public static XmlBeanFactory xmlBeanFactory;

	@BeforeAll
	public static void beforeTest() {
		xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("org/springframework/demo/demo.xml"));
	}
}
-- for lookup-method
package org.springframework.demo.method.lookup;

public abstract class Car {

	// 用于lookup-method注入
	public abstract Taxi createTaxi();

	private Taxi taxi;

	public Taxi getTaxi() {
		return taxi;
	}

	//setter注入
	public void setTaxi(Taxi taxi) {
		this.taxi = taxi;
	}
}

package org.springframework.demo.method.lookup;

public class Taxi {
	public void say() {
		System.out.println("I am a Taxi...");
	}
}

package org.springframework.demo.method.lookup;

import org.junit.jupiter.api.Test;
import org.springframework.demo.BaseTests;

public class LookUpTests extends BaseTests {

	@Test
	public void test(){
		// 测试lookup-method注入
		Car car1 = xmlBeanFactory.getBean("car", Car.class);
		Car car2 = xmlBeanFactory.getBean("car", Car.class);

		System.out.println("Car:singleton,所以animal1==animal2应该为" + (car1 == car2));

		Taxi dog1 = car1.getTaxi();
		Taxi dog2 = car2.getTaxi();
		System.out.println("Taxi:prototype,Car:singleton,未使用lookup-method注入所以dog1==dog2应该为" + (dog1 == dog2));

		//注意:这里是通过createTaxi()方法获取
		Taxi taxi3 = car1.createTaxi();
		Taxi taxi4 = car2.createTaxi();
		System.out.println("Taxi:prototype,Car:singleton,使用了lookup-method注入所以dog3==dog4应该为" + (taxi3 == taxi4));

	}
}

<!-- ====================lookup-method属性注入==================== -->
<bean id="car" class="org.springframework.demo.method.lookup.Car">
	<!--注意:下面这句配置和lookup-method注入没有关系,我们只是为了出于演示和说明配置该bean-->
	<property name="taxi" ref="taxi"/>
	<!--lookup-method注入-->
	<lookup-method name="createTaxi" bean="taxi"/>
</bean>
<bean id="taxi" class="org.springframework.demo.method.lookup.Taxi" scope="prototype"/>
-- for replace-method
package org.springframework.demo.method.replace;

public class OriginalDog {
	public void sayHello() {
		System.out.println("Hello,I am a black dog...");
	}

	public void sayHello(String name) {
		System.out.println("Hello,I am a black dog, my name is " + name);
	}
}

package org.springframework.demo.method.replace;

import org.springframework.beans.factory.support.MethodReplacer;

import java.lang.reflect.Method;
import java.util.Arrays;

public class ReplaceDog implements MethodReplacer {
	@Override
	public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
		System.out.println("Hello, I am a white dog...");

		Arrays.stream(args).forEach(str -> System.out.println("参数:" + str));
		return obj;
	}
}

package org.springframework.demo.method.replace;

import org.junit.jupiter.api.Test;
import org.springframework.demo.BaseTests;

public class ReplaceTests extends BaseTests {

	@Test
	public void test() {
		// 测试replace-method注入
		OriginalDog originalDog = xmlBeanFactory.getBean("originalDogReplaceMethod", OriginalDog.class);
		originalDog.sayHello("输出结果已经被替换了。。。");
	}
}


<!-- ====================replace-method属性注入==================== -->
<bean id="dogReplaceMethod" class="org.springframework.demo.method.replace.ReplaceDog"/>
<bean id="originalDogReplaceMethod" class="org.springframework.demo.method.replace.OriginalDog">
	<replaced-method name="sayHello" replacer="dogReplaceMethod">
		<arg-type match="java.lang.String"></arg-type>
	</replaced-method>
</bean>

2.4 实例化bean

经过了前面的一系列准备,接下来进入IOC的核心方法doCreateBean。中间涉及较多的知识点,先来了解一下doCreateBean的主要逻辑。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	// Instantiate the bean.
	// 实例化bean。
	BeanWrapper instanceWrapper = null;
	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;
	}
	// Allow post-processors to modify the merged bean definition.
	// 允许后处理器修改合并的bean定义。
	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.
	// 主动缓存单例,以便能够解析循环引用,即使是在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.
	// 初始化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.
	// 将单例bean注册到disposableBeans(LinkedHashMap)中,以方面容器关闭时回调对应bean的销毁方法
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}
	return exposedObject;
}
  • 主要逻辑:
    • 创建bean的实例
    • 允许后处理器修改合并的bean定义
    • 主动缓存单例,以便能够解析循环引用
    • 初始化bean实例
    • 异常处理
    • 将单例bean注册到disposableBeans(LinkedHashMap)中,以方面容器关闭时回调对应bean的销毁方法
    • 返回bean的实例
  • 重点分析:
    • 创建bean的实例(控制反转)
    • 初始化bean实例(依赖注入)
2.4.1 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 实例化
	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...
	// 创建相同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.
	// 无参构造函数实例化。
	return instantiateBean(beanName, mbd);
}

实例化bean的方式:

  • Supplier
  • 工厂方法:
    • 静态工厂
    • 实例工厂
  • 构造函数:
    • 有参构造函数
    • 无参构造函数
  • 快照实例化,该方式有些特殊。例如针对某个单例bean,创建完之后销毁,Spring依然会保留其解析快照,节约下次解析开销
2.4.1.1 Supplier

Supplier 接口是一个函数式接口,下面演示一下使用方式:

@Test
public void SupplierTest() {
	AnnotationConfigApplicationContext context =
			new AnnotationConfigApplicationContext("org/springframework/demo/demo.xml");
	context.registerBean("dog", Dog.class, new Supplier<Dog>() {
		@Override
		public Dog get() {
			return new Dog();
		}
	});
	context.getBean("dog", Dog.class).sayHello();
}

再来看一下Supplier接口的定义:

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

通过get方法返回bean的实例。这种实例化方式源码很简单,不多赘述。

2.4.1.2 静态工厂

该方式源码比较简单,只演示一下其使用方式:

package org.springframework.demo.factory;

import org.springframework.demo.Dog;

public class DogStaticFactory {

	// 静态工厂方法
	public static Dog newInstance(String name, int age) {
		// 返回需要的Bean实例
		return new Dog(name, age);
	}
}

<!-- 静态工厂方法实例化 -->
<bean id="dog" class="org.springframework.demo.factory.DogStaticFactory" factory-method="newInstance">
	<!-- 指定构造器参数 index对应构造器中参数的位置 -->
	<constructor-arg index="0" value="小明"/>
	<constructor-arg index="1" value="3"/>
</bean>
2.4.1.3 实例工厂

该方式源码比较简单,只演示一下其使用方式:

package org.springframework.demo.factory;

import org.springframework.demo.Dog;

public class DogFactory {

	public Dog newInstance(String name, int age) {
		return new Dog(name, age);
	}
}

<!-- 实例工厂方法实例化 -->
<bean id="dogFactory" class="org.springframework.demo.factory.DogFactory"/>
<!-- 不能指定class属性,此时必须使用factory-bean属性来指定工厂Bean,factory-method属性指定实例化Bean的方法 -->
<bean id="dog" factory-bean="dogFactory" factory-method="newInstance">
	<constructor-arg index="0" value="小明"/>
	<constructor-arg index="1" value="3"/>
</bean>
2.4.1.4 有参构造函数

先来看一下使用有参构造函数的条件:

Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null
		|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR
		|| mbd.hasConstructorArgumentValues()
		|| !ObjectUtils.isEmpty(args)) {
	return autowireConstructor(beanName, mbd, ctors, args);
}
  • determineConstructorsFromBeanPostProcessors 解析的构造函数不为空
  • mbd.getResolvedAutowireMode 解析自动装配类型为构造函数
  • mbd.hasConstructorArgumentValues 通过配置文件指定了构造函数参数
  • !ObjectUtils.isEmpty(args) 获取bean的时候显示指定了构造函数参数
  • 有参构造函数实例化的难点在于对构造函数的解析,代码极为繁杂,本文不展开分析
2.4.1.5 无参构造函数
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
	try {
		Object beanInstance;
		if (System.getSecurityManager() != null) {
			beanInstance = AccessController.doPrivileged(
					(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
					getAccessControlContext());
		}
		else {
			// 获取实例化策略,并实例化bean
			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);
	}
}
2.4.2 无参实例化策略详解


上文提到了IOC实例化bean的几种策略,接下来的小节,重点分析无参、有参两种实例化策略。因为无参策略较为简单,所以先分析该策略。

入口代码:

// 获取实例化策略,并实例化bean
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
2.4.2.1 getInstantiationStrategy 获取实例化策略
/** Strategy for creating bean instances. 创建 bean 实例的策略。*/
private InstantiationStrategy instantiationStrategy;

/**
 * Set the instantiation strategy to use for creating bean instances.
 * Default is CglibSubclassingInstantiationStrategy.
 * 设置用于创建 bean 实例的实例化策略。 默认为 CglibSubclassingInstantiationStrategy。
 * @see CglibSubclassingInstantiationStrategy
 */
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
	this.instantiationStrategy = instantiationStrategy;
}

/**
 * Return the instantiation strategy to use for creating bean instances.
 * 返回用于创建 bean 实例的实例化策略
 */
protected InstantiationStrategy getInstantiationStrategy() {
	return this.instantiationStrategy;
}

从代码中可以看到,IOC通过InstantiationStrategy接口来管理实例化策略,并且默认为CglibSubclassingInstantiationStrategy。但是IOC容器并没有显示的调用setInstantiationStrategy设置实例化策略,而是通过AbstractAutowireCapableBeanFactory的构造方法来创建实例化策略。

public AbstractAutowireCapableBeanFactory() {
	super();
	ignoreDependencyInterface(BeanNameAware.class);
	ignoreDependencyInterface(BeanFactoryAware.class);
	ignoreDependencyInterface(BeanClassLoaderAware.class);
	if (NativeDetector.inNativeImage()) {
		this.instantiationStrategy = new SimpleInstantiationStrategy();
	}
	else {
	   // 实例化 CglibSubclassingInstantiationStrategy
		this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
	}
}
2.4.2.2 实例化策略概览

上一步拿到实例化策略后,就可以实例化bean了。

@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);
				}
			}
		}
		// 实例化
		return BeanUtils.instantiateClass(constructorToUse);
	}
	else {
		// Must generate CGLIB subclass.
		// 存在方法注入,必须使用 CGLIB
		return instantiateWithMethodInjection(bd, beanName, owner);
	}
}

无方法注入,使用反射;否则,必须使用CGLIB

2.4.2.3 反射
  • 获取构造方法
    • constructorToUse = clazz.getDeclaredConstructor(); 通过Class类的getDeclaredConstructor()方法获取构造函数。因为这里是无参策略,所以无需传递任何参数。获取到构造方法后,再将其缓存到resolvedConstructorOrFactoryMethod中,方便下次使用。
  • 通过BeanUtils创建对象实例
    • 通过Constructor类的newInstance方法创建对象实例
2.4.2.4 CGLIB

若存在方法注入(replace-method、lookup-method)则必须使用CGLIB。

public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
	// 创建增强子类
	Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
	Object instance;
	// 无参实例化
	if (ctor == null) {
		instance = BeanUtils.instantiateClass(subclass);
	}
	// 有参实例化
	else {
		try {
			// 获取有参构造函数
			Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes(
			// 实例化
			instance = enhancedSubclassConstructor.newInstance(args);
		}
		catch (Exception ex) {
			throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
					"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + 
		}
	}
	// SPR-10785: set callbacks directly on the instance instead of in the
	// enhanced class (via the Enhancer) in order to avoid memory leaks.
	// 为了避免内存泄漏,直接在实例上设置回调,而不是在增强类中(通过Enhancer)。
	Factory factory = (Factory) instance;
	factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
			new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
			new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
	return instance;
}

首先创建增强子类:

/**
 * Create an enhanced subclass of the bean class for the provided bean definition, using CGLIB.
 * 使用 CGLIB 为提供的 bean 定义创建 bean 类的增强子类。
 */
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
	Enhancer enhancer = new Enhancer();
	enhancer.setSuperclass(beanDefinition.getBeanClass());
	enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
	if (this.owner instanceof ConfigurableBeanFactory) {
		ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
		enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
	}
	enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
	enhancer.setCallbackTypes(CALLBACK_TYPES);
	return enhancer.createClass();
}

Spring使用了Enhancer来创建增强子类,因为是动态字节码,所以我们需要将生成的增强文件保存到磁盘。在测试方法中添加:

// 替换成自己的路径
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/liyanchao/Downloads");

OK,接下来就可以看到生成的增强子类了,因为代码较多,只粘贴核心代码:

public class OriginalDog$$EnhancerBySpringCGLIB$$236d11d6 extends OriginalDog implements Factory {
    public final void sayHello() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_2;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_2;
        }
        if (var10000 != null) {
            // 拦截方法
            var10000.intercept(this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
        } else {
            super.sayHello();
        }
    }
}

有了增强子类后,接下来通过instance = BeanUtils.instantiateClass(subclass);创建对象实例,注意:这里创建的实例已经不是我们原始Bean的实例了,而是增强子类的实例。

当调用增强类中的方法时,会被intercept()方法拦截:

// replace_method
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
	ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
	Assert.state(ro != null, "ReplaceOverride not found");
	// TODO could cache if a singleton for minor performance optimization
	// 获取方法注入类实例
	MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
	return mr.reimplement(obj, method, args);
}
// lookup_method
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
	// Cast is safe, as CallbackFilter filters are used selectively.
	LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
	Assert.state(lo != null, "LookupOverride not found");
	Object[] argsToUse = (args.length > 0 ? args : null);  // if no-arg, don't insist on args at all
	if (StringUtils.hasText(lo.getBeanName())) {
		Object bean = (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) :
				this.owner.getBean(lo.getBeanName()));
		// Detect package-protected NullBean instance through equals(null) check
		return (bean.equals(null) ? null : bean);
	}
	else {
		// Find target bean matching the (potentially generic) method return type
		ResolvableType genericReturnType = ResolvableType.forMethodReturnType(method);
		return (argsToUse != null ? this.owner.getBeanProvider(genericReturnType).getObject(argsToUse) :
				this.owner.getBeanProvider(genericReturnType).getObject());
	}
}
2.4.3 初始化bean实例

前文两个小节分2.4.12.4.2析了创建bean的实例(控制反转),接下来分析**初始化bean实例(依赖注入)。**在doCreateBean方法中有:

// Initialize the bean instance.
// 初始化bean实例。
Object exposedObject = bean;
try {
	populateBean(beanName, mbd, instanceWrapper);
	exposedObject = initializeBean(beanName, exposedObject, mbd);
}
  • 步骤:
    • 填充 bean 属性
    • 初始化给定的 bean 实例
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// 实例为空
	if (bw == null) {
		if (mbd.hasPropertyValues()) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		else {
			// Skip property population phase for null instance.
			return;
		}
	}
	// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
	// state of the bean before properties are set. This can be used, for example,
	// to support styles of field injection.
	// 应用 InstantiationAwareBeanPostProcessors 处理器
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
				return;
			}
		}
	}
	// 获取bean的属性
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
	// 判断注入模式
	int resolvedAutowireMode = mbd.getResolvedAutowireMode();
	// ByName 或 ByType
	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;
	}
	// 判断是否有 InstantiationAwareBeanPostProcessor 处理器
	// 该类型处理器通常用于抑制特定目标 bean 的默认实例化,一般用做 Spring 框架内部使用
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
			if (pvsToUse == null) {
				if (filteredPds == null) {
					filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
				}
				pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					return;
				}
			}
			pvs = pvsToUse;
		}
	}
	if (needsDepCheck) {
		if (filteredPds == null) {
			filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		}
		checkDependencies(beanName, mbd, filteredPds, pvs);
	}
	// 应用给定的属性值
	if (pvs != null) {
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}
  • 步骤:
    • 应用 InstantiationAwareBeanPostProcessors 处理器
    • 解析自动装配类型,并处理by_name、by_type两种类型
    • 应用 InstantiationAwareBeanPostProcessor 处理器
    • 应用给定的属性值
  • 简析:
    • InstantiationAwareBeanPostProcessors、InstantiationAwareBeanPostProcessor这两个处理器,后续章节分析
    • by_name、by_type 留到ApplicationContext容器部分分析
    • 方法代码看似繁杂,这里我们只关注applyPropertyValues()方法即可
  • 小节,综上所述,我们只需要分析:
    • populateBean 方法的 applyPropertyValues 方法
    • initializeBean 方法
2.4.3.1 填充 bean 属性

applyPropertyValues 方法极为繁杂,只抽取其核心代码分析:

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    // 省略部分代码。。。 
    
    // 解析 PropertyValue
    Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
    
    // 转换 resolvedValue
    if (convertible) {
        convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
    }
    // 应用属性值
    try {
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    
    // 省略部分代码。。。 
}

步骤:

  • 解析 PropertyValue
  • 转换 resolvedValue
  • 应用属性值
2.4.3.1.1 解析 PropertyValue

解析 PropertyValue 的代码繁杂,这里先概览一下其支持的类型:

  • RuntimeBeanReference
  • RuntimeBeanNameReference
  • BeanDefinitionHolder
  • BeanDefinition
  • DependencyDescriptor
  • ManagedArray
  • ManagedList
  • ManagedSet
  • ManagedMap
  • ManagedProperties
  • TypedStringValue
  • NullBean

以RuntimeBeanReference为例,分析一下其解析过程:

if (value instanceof RuntimeBeanReference) {
	RuntimeBeanReference ref = (RuntimeBeanReference) value;
	return resolveReference(argName, ref);
}
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
	try {
		Object bean;
		Class<?> beanType = ref.getBeanType();
		// 从父 beanFactory 中查找
		if (ref.isToParent()) {
			BeanFactory parent = this.beanFactory.getParentBeanFactory();
			if (parent == null) {
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Cannot resolve reference to bean " + ref +
								" in parent factory: no parent factory available");
			}
			if (beanType != null) {
				bean = parent.getBean(beanType);
			}
			else {
				bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
			}
		}
		// 从当前 beanFactory 中查找
		else {
			String resolvedName;
			if (beanType != null) {
				NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
				bean = namedBean.getBeanInstance();
				resolvedName = namedBean.getBeanName();
			}
			else {
				// 解析 bean 名称
				resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
				// 获取 bean 实例
				bean = this.beanFactory.getBean(resolvedName);
			}
			this.beanFactory.registerDependentBean(resolvedName, this.beanName);
		}
		if (bean instanceof NullBean) {
			bean = null;
		}
		return bean;
	}
	catch (BeansException ex) {
		throw new BeanCreationException(
				this.beanDefinition.getResourceDescription(), this.beanName,
				"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
	}
}

其它类型不一一分析。

2.4.3.1.2 转换 resolvedValue
public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
		@Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {
	// 省略部分代码。。。
	if (requiredType != null) {
		// Try to apply some standard type conversion rules if appropriate.
		if (convertedValue != null) {
			if (Object.class == requiredType) {
				return (T) convertedValue;
			}
			else if (requiredType.isArray()) {
				// Array required -> apply appropriate conversion of elements.
				if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
					convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
				}
				return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
			}
			else if (convertedValue instanceof Collection) {
				// Convert elements to target type, if determined.
				convertedValue = convertToTypedCollection(
						(Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
				standardConversion = true;
			}
			else if (convertedValue instanceof Map) {
				// Convert keys and values to respective target type, if determined.
				convertedValue = convertToTypedMap(
						(Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
				standardConversion = true;
			}
			if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
				convertedValue = Array.get(convertedValue, 0);
				standardConversion = true;
			}
			if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
				// We can stringify any primitive value...
				return (T) convertedValue.toString();
			}
			else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
				if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
					try {
						Constructor<T> strCtor = requiredType.getConstructor(String.class);
						return BeanUtils.instantiateClass(strCtor, convertedValue);
					}
					catch (NoSuchMethodException ex) {
						// proceed with field lookup
						if (logger.isTraceEnabled()) {
							logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex);
						}
					}
					catch (Exception ex) {
						if (logger.isDebugEnabled()) {
							logger.debug("Construction via String failed for type [" + requiredType.getName() + "]", ex);
						}
					}
				}
				String trimmedValue = ((String) convertedValue).trim();
				if (requiredType.isEnum() && trimmedValue.isEmpty()) {
					// It's an empty enum identifier: reset the enum value to null.
					return null;
				}
				convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
				standardConversion = true;
			}
			else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
				convertedValue = NumberUtils.convertNumberToTargetClass(
						(Number) convertedValue, (Class<Number>) requiredType);
				standardConversion = true;
			}
		}
		else {
			// convertedValue == null
			if (requiredType == Optional.class) {
				convertedValue = Optional.empty();
			}
		}
		if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
			if (conversionAttemptEx != null) {
				// Original exception from former ConversionService call above...
				throw conversionAttemptEx;
			}
			else if (conversionService != null && typeDescriptor != null) {
				// ConversionService not tried before, probably custom editor found
				// but editor couldn't produce the required type...
				TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
				if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
					return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
				}
			}
			// Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
			StringBuilder msg = new StringBuilder();
			msg.append("Cannot convert value of type '").append(ClassUtils.getDescriptiveType(newValue));
			msg.append("' to required type '").append(ClassUtils.getQualifiedName(requiredType)).append('\'');
			if (propertyName != null) {
				msg.append(" for property '").append(propertyName).append('\'');
			}
			if (editor != null) {
				msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
						"] returned inappropriate value of type '").append(
						ClassUtils.getDescriptiveType(convertedValue)).append('\'');
				throw new IllegalArgumentException(msg.toString());
			}
			else {
				msg.append(": no matching editors or conversion strategy found");
				throw new IllegalStateException(msg.toString());
			}
		}
	}
	// 省略部分代码。。。
	return (T) convertedValue;
}
2.4.3.1.3 应用属性值
// AbstractPropertyAccessor.java
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException {
	// 省略部分代码。。。
	try {
		for (PropertyValue pv : propertyValues) {
			try {
				setPropertyValue(pv);
			}
	// 省略部分代码。。。
}

调用过程的代码不一一粘贴,最终会调用到 BeanWrapperImpl.java 的 setValue 方法:

public void setValue(@Nullable Object value) throws Exception {
  // 获取 writeMethod,即 set 方法
	Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
			((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
			this.pd.getWriteMethod());
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			ReflectionUtils.makeAccessible(writeMethod);
			return null;
		});
		try {
			AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
					() -> writeMethod.invoke(getWrappedInstance(), value), acc);
		}
		catch (PrivilegedActionException ex) {
			throw ex.getException();
		}
	}
	else {
		ReflectionUtils.makeAccessible(writeMethod);
		// 调用 JDK Method 类的 invoke 方法,设置属性值
		writeMethod.invoke(getWrappedInstance(), value);
	}
}
2.4.3.2 初始化 bean 实例
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 {
		// 调用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口
		invokeAwareMethods(beanName, bean);
	}
	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		// 调用 postProcessBeforeInitialization 方法
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}
	try {
		// 调用 初始化方法
		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()) {
		// 调用 postProcessAfterInitialization 方法
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}

initializeBean 主要涉及到与 bean 生命周期相关的接口,比较简单,不一一叙述。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闲来也无事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值