Spring Bean的实例化源码解析

声明:文章内容仅代表个人对源码的理解和观点,可能存在理解错误的地方,欢迎留言探讨、指正。不喜勿喷,谢谢。
个人用的是 v5.2.4.RELEASE 版本的源码,因为几年前阅读时已经写了一些注释,所以没有拉取最新的源码,与最新的源码会存在一定的差异。

可以将Bean实例化看做是 Bean生命周期 的第一步,实例化Bean的主流程在AbstractAutowireCapableBeanFactory.createBeanInstance(),该方法在AbstractAutowireCapableBeanFactory.doCreateBean()中被调用。doCreateBean方法的部分源码如下:

// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
		throws BeanCreationException {
   
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
   
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	/*
	 * 第一步:实例化Bean。
	 * 使用合适的实例化策略来实例化新的Bean:回调函数、工厂方法、带参的构造函数、无参构造函数。默认使用无参构造器实例化Bean。
	 * 构造函数自动注入发生在这一步
	 */
	if (instanceWrapper == null) {
    // 为null,说明不是FactoryBean,那么调用工厂或者构造函数实例化Bean
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	// 省略掉大量代码,这些代码用于初始化Bean、属性赋值、循环依赖处理等
	return exposedObject;
}

createBeanInstance

// AbstractAutowireCapableBeanFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   
	// Make sure bean class is actually resolved at this point.
	// 从bean定义中解析出当前bean的class对象
	Class<?> beanClass = resolveBeanClass(mbd, beanName);

	// 检测类的访问权限。对于非public类,默认是允许访问的;若被设置为禁止访问非public的类,则这里会抛出异常
	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());
	}

	/*
	 * 这是Spring5提供的一种替换工厂方法的方式,提供一个回调函数实例化Bean
	 * 自己创建BeanDefinition对象,然后注册到IoC容器中时,有可能使用到这种方式
	 */
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	if (instanceSupplier != null) {
   
	    // 这里的代码很简单,就是执行回调函数获取Bean的实例
		return obtainFromSupplier(instanceSupplier, beanName);
	}

	/*
	 * 判断是不是使用工厂实例化Bean,工厂方法名称不为空,即表示使用工厂方法进行实例化。
	 * 无论是静态工厂还是实例工厂,都是走这一步
	 * 通过Java配置类配置的Bean,实例化方式采用的是实例工厂方法,工厂实例就是Java配置类的代理对象
	 */
	if (mbd.getFactoryMethodName() != null) {
   
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}

	// Shortcut when re-creating the same bean...
	boolean resolved = false; // 判断Bean定义中的构造函数或者工厂方法是否已被解析过
	boolean autowireNecessary = false; // 有没有必要进行依赖注入
	if (args == null) {
    // getBean方法传入的参数为null
		synchronized (mbd.constructorArgumentLock) {
   
			/*
			 * 判断bean定义中的resolvedConstructorOrFactoryMethod属性是否有值
			 * 该属性用来缓存构造函数或者工厂方法,Bean在第一次被实例化的时候,会将解析得到的构造函数或者工厂方法赋值给这个属性
			 * 对于非单例模式的Bean来说,只需要解析一次Bean定义中的构造函数或工厂方法即可,后续可以直接从Bean定义中拿来使用
			 */
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
   
				resolved = true; // 标记构造函数已被解析过了,原型等非单例模式的Bean,从第二次实例化开始就会进入这里
				// 构造函数参数是否被解析过?当使用有参构造函数或者工厂方法实例化Bean时,该属性会被设置为true
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	if (resolved) {
    // 已经解析过了,直接实例化Bean即可
		if (autowireNecessary) {
   
			// 使用有参构造函数实例化对象
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
   
			// 使用无参构造函数实例化对象
			return instantiateBean(beanName, mbd);
		}
	}

	// Candidate constructors for autowiring?
	/*
	 * 调用处理器(AutowiredAnnotationBeanPostProcessor),获取用于实例化Bean的构造函数
	 * 如果有多个构造函数,构造函数上都有@Autowired注解,无论required属性为何值,都会抛出异常,如果仅有一个构造函数有注解,则使用这个
	 * 如果只有xml配置,这里一般都是返回null
	 */
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	/*
	 * 1. 上一行后置处理器解析出的构造函数不为null
	 * 2. bean定义中指定自动注入模式是构造器注入
	 *    <bean id="order" class="org.xxx.Order" autowire="constructor"/> 这种方式定义的Bean即是构造函数自动注入
	 *    在构造函数上使用了@Autowire注解,也是构造函数自动注入
	 *    通过Java配置类定义的Bean,无论方法参数是否有值,都会被解析为构造函数自动注入
	 *    在Bean定义时,显式指定了构造函数参数(constructor-arg),则不是构造函数自动注入(注意,这里指的自动注入模式)
	 *    静态工厂和实例工厂定义的Bean,不是构造函数自动注入
	 * 3. bean定义中指定了构造函数,无论参数是通过名称、类型、下标配置,都是走这一步
	 * 4. 在外层,调用getBean方法传入的构造器函数参数类型不为null
	 * 四个条件有一个满足,就使用指定的构造函数进行实例化Bean
	 */
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
   
		// 使用指定的构造函数实例化对象,构造函数自动注入在这里完成
		return autowireConstructor(beanName, mbd, ctors, args);
	}

	// Preferred constructors for default construction?
	/*
	 * bean定义中的首选构造器
	 * 目前只有 GenericApplicationContext#ClassDerivedBeanDefinition类的这个方法有返回值,其它都是返回null
	 * 所以,Bean的实例化,基本不会走这一步
	 */
	ctors = mbd.getPreferredConstructors();
	if (ctors != null) {
   
		// 实例化Bean
		return autowireConstructor(beanName, mbd, ctors, null);
	}

	// No special handling: simply use no-arg constructor.
	// 如果前面的条件都不匹配,则使用无参构造函数实例化对象
	return instantiateBean(beanName, mbd);
}

从上面的源码可以看出,Spring提供了三种实例化Bean的方式:

  1. Supplier回调函数。这是从Spring5开始提供的一种实例化方式。通过工厂、构造函数实例化对象时,Spring使用的都是反射,而反射的性能相对较差。Supplier回调函数可以自定义实例化过程,无须通过反射调用,直接执行函数即可。
  2. 工厂方法。又分为静态工厂和实例工厂。
  3. 构造函数。有参构造函数、无参构造函数。当没有配置使用哪个构造函数时,默认使用无参构造函数实例化。

还有一种实例化方式是FactoryBean,例如Spring Cloud中实例化FeignClient对象,使用的就是FeignClientFactoryBean。这种方式的流程相对长一些、麻烦一些,这篇文章不做分析。

在Java配置类中配置的Bean,使用的是实例工厂实例化,实例工厂是Java配置类的代理对象,这个代理对象是在Spring解析Java配置类时创建的。

对于非单例模式的Bean,Spring做了一些性能优化,只有第一次实例化Bean时,才需要解析Bean定义的构造函数、工厂方法、参数值等,解析完成之后会将这些数据回写到Bean定义对象的对应属性。下次再创建时,直接从Bean定义中获取即可,无须再次解析。

实例化Bean的方式

回调函数实例化Bean

通过回调函数实例化Bean的代码非常简单,直接执行Bean定义中的回调函数,无须解析参数,也不需要进行反射调用。源码如下:

// AbstractAutowireCapableBeanFactory
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
   
	Object instance;

	// 设置当前正在实例化的Bean的名称到ThreadLocal
	String outerBean = this.currentlyCreatedBean.get();
	this.currentlyCreatedBean.set(beanName);
	try {
   
		instance = instanceSupplier.get(); // 调用函数,拿到Bean实例
	}
	finally {
   
		// 重置ThreadLocal
		if (outerBean != null) {
   
			this.currentlyCreatedBean.set(outerBean);
		}
		else {
   
			this.currentlyCreatedBean.remove();
		}
	}

	if (instance == null) {
   
		instance = new NullBean();
	}

	// BeanWrapper接口提供了一些操作目标对象属性值的方法
	BeanWrapper bw = new BeanWrapperImpl(instance);
	initBeanWrapper(bw);
	return bw;
}

配置回调函数的示例

提供一个简单的回调函数配置示例

public class MemberRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
   

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
   
		RootBeanDefinition bd = new RootBeanDefinition();
		bd.setBeanClass(Member.class);
		bd.setInstanceSupplier(Member::new); // 这里注册一个回调函数
		registry.registerBeanDefinition("member", bd);
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
   
	}
}

工厂方法实例化Bean

使用工厂方法实例化Bean的主要代码在ConstructorResolver.instantiateUsingFactoryMethod()方法中,AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod()方法仅仅只有一行代码。具体源码如下:

// AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateUsingFactoryMethod(
	String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
   

return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
// ConstructorResolver
public BeanWrapper instantiateUsingFactoryMethod(
		String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
   

	BeanWrapperImpl bw = new BeanWrapperImpl();
	this.beanFactory.initBeanWrapper(bw);

	// 实例工厂Bean对象,如果是静态工厂,值为null
	Object factoryBean;
	// 工厂的类型
	Class<?> factoryClass;
	// 是否静态工厂
	boolean isStatic;

	// 实例工厂的BeanName,如果是静态工厂,则值为null
	String factoryBeanName = mbd.getFactoryBeanName();
	if (factoryBeanName != null) {
   
		// 如果是实例工厂,进入这个分支
		// 实例工厂的Bean名称和需要使用工厂实例化的Bean对象的名称相同,则抛出异常
		if (factoryBeanName.equals(beanName)) {
   
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
					"factory-bean reference points back to the same bean definition");
		}
		// 从IoC容器中获取实例工厂对象
		factoryBean = this.beanFactory.getBean(factoryBeanName);
		// 单例Bean,并且在IoC容器的一级缓存中已存在,说明这个Bean已经被创建过了,不能再次创建,抛出异常
		if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
   
			throw new ImplicitlyAppearedSingletonException();
		}
		factoryClass = factoryBean.getClass(); // 实例工厂的类名,这里可能得到CGLIB生成的子类名称
		isStatic = false;
	}
	else {
   
		// It's a static factory method on the bean class.
		// 如果是静态工厂,则进入这个分支
		if (!mbd.hasBeanClass()) {
   
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
					"bean definition declares neither a bean class nor a factory-bean reference");
		}
		factoryBean = null;
		factoryClass = mbd.getBeanClass(); // 静态工厂的类名
		isStatic = true;
	}

	Method factoryMethodToUse = null; // 用于实例化Bean的工厂方法
	ArgumentsHolder argsHolderToUse = null; // 持有 用于实例化Bean的参数 对象
	Object[] argsToUse = null; // 用于实例化Bean的参数

	if (explicitArgs != null) {
   
		argsToUse = explicitArgs;
	}
	else {
   
		Object[] argsToResolve = null;
		synchronized (mbd.constructorArgumentLock) {
   
			/*
			 * 工厂方法是否已经被解析过
			 * 第一次实例化Bean时,解析Bean定义,找到实例化Bean的工厂方法,
			 * 然后会将工厂方法回写到Bean定义中的resolvedConstructorOrFactoryMethod属性,并且constructorArgumentsResolved属性也会被设置为true。
			 * 当下次再需要实例化这个Bean时,就无须再次解析,直接从Bean定义中获取即可,这是对非单例作用域的Bean实例化过程的优化
			 */
			factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
			if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
   
				// Found a cached factory method...
				argsToUse = mbd.resolvedConstructorArguments;
				if (argsToUse == null) {
   
					argsToResolve = mbd.preparedConstructorArguments;
				}
			}
		}
		if (argsToResolve != null) {
   
			argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
		}
	}

	if (factoryMethodToUse == null || argsToUse == null) {
   
		// Need to determine the factory method...
		// Try all methods with this name to see if they match the given arguments.
		// 获取工厂的实际类型,如果是CGLIB生成的子类,则返回原始类;否则返回的就是参数值
		factoryClass = ClassUtils.getUserClass(factoryClass);

		List<Method> candidates = null; // 可用于实例化Bean的工厂方法
		if (mbd.isFactoryMethodUnique) {
    // 如果是宰Java配置类中配置的Bean,会走这块代码
			if (factoryMethodToUse == null) {
   
				factoryMethodToUse = mbd.getResolvedFactoryMethod();
			}
			if (factoryMethodToUse != null) {
   
				candidates = Collections.singletonList(factoryMethodToUse);
			}
		}
		if (candidates == null) {
    // 如果是静态工厂或者实例工厂,会走块代码
			candidates 
Spring Bean的生命周期可以分为以下几个阶段:实例化、属性赋值、初始化、销毁。 1. 实例化阶段:Spring容器根据配置信息或注解创建Bean的实例。在这个阶段,Spring会调用Bean的构造方法来创建对象。 2. 属性赋值阶段:在实例化后,Spring会通过依赖注入的方式将属性值注入到Bean中。这可以通过XML配置文件、注解或Java代码来完成。 3. 初始化阶段:在属性赋值完成后,Spring会调用Bean的初始化方法。初始化方法可以通过实现InitializingBean接口的afterPropertiesSet()方法,或者在配置文件中使用init-method属性指定。 4. 销毁阶段:当容器关闭时,Spring会调用Bean的销毁方法来释放资源。销毁方法可以通过实现DisposableBean接口的destroy()方法,或者在配置文件中使用destroy-method属性指定。 下面是Spring Bean生命周期的源码解析: 1. 实例化阶段:Spring使用反射机制调用Bean的构造方法来创建对象。 2. 属性赋值阶段:Spring使用反射机制或者BeanWrapper将属性值注入到Bean中。 3. 初始化阶段:Spring会判断是否实现了InitializingBean接口,如果是,则调用afterPropertiesSet()方法;如果没有,则判断是否配置了init-method属性,如果有,则调用指定的初始化方法。 4. 销毁阶段:Spring会判断是否实现了DisposableBean接口,如果是,则调用destroy()方法;如果没有,则判断是否配置了destroy-method属性,如果有,则调用指定的销毁方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值