Spring源码学习三:创建Bean

Spring源码学习三:创建Bean

更多请关注:https://t.zsxq.com/fhroW

创建Bean

入口:

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

概念

抽象BeanDefinition

以下代码中注入的person生成的BeanDefinition就是抽象的,抽象的BeanDefinition是不会实例化的,它的作用主要是BeanDefinition的属性继承
这里的集成与类的集成无关,且BeanDefinition的集成并不要求父BeanDefinition是抽象的

<bean id="person" class="com.zhouyu.service.Person" scope="prototype" abstract=true />
<bean id="user" class="com.zhouyu.service.User" parent="person"/>

合并BeanDefinition

  • 如果有BeanDefinition继承的情况,则会合并
    实例化子BeanDefinition时会使用父的属性,当然如果子中指定了属性,就用子的,不指定就用父的。
    比如上文中person是多例的,而user没有指定scope(默认是单例),则user就会是多例的
  • 合并会生成一个新的RootBeanDefition,不会去修改beanDefinitionMap中的元素。实例化时用RootBeanDefinition去实例化
  • 合并时如果BeanDefinition有parent,则合并,取出parent中属性去判断、去合并,如果没有parent,则直接将BeanDefinition转化为RootBeanDefinition
  • 合并时存在多层parent的情况,用递归解决

FactoryBean

Factory就是由用户自己去创建Bean,通过FactoryBean创建的Bean只会经历初始化后的步骤,不会经历初始化和初始化前的步骤(因为要实现AOP,所以要实现初始化后的步骤)
定义FactroyBean

@Component
public class ZhouyuFactoryBean implements FactoryBean {

	@Override
	public Object getObject() throws Exception {
		UserService userService = new UserService();

		return userService;
	}

	@Override
	public Class<?> getObjectType() {
		return UserService.class;
	}
}
  • 此时通过BeanName: zhouyuFactoryBean拿到的Bean就是UserService类型的,通过BeanName:&zhouyuFactoryBean就可以拿到ZhouyuFactoryBean类型的Bean。

  • FactoryBean会生成两个Bean,一个FactoryBean,一个真实的Bean,FactoryBean存放在单例池中,真实的Bean存放在factoryBeanMap中

  • 实现FactoryBean接口时getObject方法是在getBean时调用的,如果实现的是SmartFactoryBean,且设置了属性之后,getObject方法会在spring启动时执行

创建过程

扫描之后就会创建非懒加载的单例Bean

  • 1:循环所有的BeanName,找出非懒加载的单例Bean,并创建

其中处理了FactoryBean,如果是FactoryBean

  • 2:所有的单例Bean创建之后,再循环所有的BeanName,找出实现了SmartInitializingSingleton接口的类,并执行它的afterSingletonsInstantiated()方法

注意该方法是所有的非懒加载的单例Bean创建完成后调用的

创建过程代码

代码中省略了日志、JDK安全管理器、JFR

	@Override
	public void preInstantiateSingletons() throws BeansException {
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		for (String beanName : beanNames) {
			// 获取合并后的BeanDefinition
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					// 获取FactoryBean对象
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());
						if (isEagerInit) {
							// 创建真正的Bean对象(getObject()返回的对象)
							getBean(beanName);
						}
					}
				}
				else {
					// 创建Bean对象
					getBean(beanName);
				}
			}
		}

		// 所有的非懒加载单例Bean都创建完了后
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				//执行用户定义的方法
				smartSingleton.afterSingletonsInstantiated();
				
			}
		}
	}

getBean()方法

在创建Bean过程中,具体的创建是非常重要的。上文一笔带过,现在详细了解。

getBean方法虽然名字叫get,但如果获取不到就会去创建Bean,在Spring启动后创建Bean时调用getBean实际上就是去创建,用户在获取Bean时也会调用,是真的只是去获取,因为此时非懒加载单例Bean已经创建好了。

  • 转化BeanName
    getBean方法传进来的name可能是&xxx或者是别名,transformedBeanName会处理这个name &xxx处理为xxx ,别名处理为真名

  • 尝试去获取Bean
    先从单例池中去取,取不到再去父容器中取,还取不到就开始创建

  • 检查RootBeanDefinition
    检查是不是抽象的类,是则报错,检查有无@DependsOn引起的循环依赖

  • 根据scope去创建Bean
    如果是单例的则创建并存入单例池,原型的则直接创建,其他Scope做相应处理
    如scope=request,也会在创建后将Bean存入map中,以此来保证同一个请求中用一个BeanName取到的是同一个对象

  • 检查取到的Bean类型是否匹配

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) {
	// 1:转化BeanName
	String beanName = transformedBeanName(name);
	Object beanInstance;
	//从单例池中获取,如果存在直接返回了,注意这里会执行FactoryBean的getObject方法
	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 + "'");
			}
		}
		// 如果sharedInstance是FactoryBean,那么就调用getObject()返回对象
		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);
		}
		//尝试从父容器中去获取Bean
		BeanFactory parentBeanFactory = getParentBeanFactory();
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			// Not found -> check parent.
			// &&&&xxx---->&xxx
			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);
		}
		if (requiredType != null) {
				beanCreation.tag("beanType", requiredType::toString);
		}
		//开始创建,先把RootBeanDefinition拿出来
		RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		// 检查BeanDefinition是不是Abstract的
		checkMergedBeanDefinition(mbd, beanName, args);
		// 根据有无@DependsOn注解引起的循环依赖
		String[] dependsOn = mbd.getDependsOn();
		if (dependsOn != null) {
			// dependsOn表示当前beanName所依赖的,当前Bean创建之前dependsOn所依赖的Bean必须已经创建好了
			for (String dep : dependsOn) {
				// beanName是不是被dep依赖了,如果是则出现了循环依赖
				if (isDependent(beanName, dep)) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
				}
				// dep被beanName依赖了,存入dependentBeanMap中,dep为key,beanName为value
				registerDependentBean(dep, beanName);
				// 创建所依赖的bean
				getBean(dep);
			}
		}
		//根据不同的作用域去创建Bean,单例Bean创建后存入单例池,原型Bean直接创建
		if (mbd.isSingleton()) {
			//这里的方法引用,是在get没有找到的时候去执行的
			//getSingleton方法中有添加到单例池的逻辑
			sharedInstance = getSingleton(beanName, () -> {
				return createBean(beanName, mbd, args);
			});
			//每个Scope最终都会调用这个方法,这个方法会处理FactoryBean,如果你传的是&xxx,上文已经处理过名字了(beanName),但是这里会把原name也传进去,用来判断你想要的是FactoryBean还是真实Bean
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
		}
		//原型Bean
		else if (mbd.isPrototype()) {
			Object prototypeInstance = null;
			beforePrototypeCreation(beanName);
			prototypeInstance = createBean(beanName, mbd, args);
			afterPrototypeCreation(beanName);
		}
		//scope是spring启动的时候注册进容器的,springMVC、SpringBoor中会注入request、session的Scope,在这里就会处理
		//比如保证同一个请求中同一个BeanName获取到的Bean是同一个
		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 {  // session.getAttriute(beaName)  setAttri
				Object scopedInstance = scope.get(beanName, () -> {
					beforePrototypeCreation(beanName);
					return createBean(beanName, mbd, args);
					afterPrototypeCreation(beanName);
				});
				beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
			}
			catch (IllegalStateException ex) {
					throw new ScopeNotActiveException(beanName, scopeName, ex);
			}
		}
	// 检查通过name所获得到的beanInstance的类型是否是requiredType
	return adaptBeanInstance(name, beanInstance, requiredType);
}

createBean方法

getBean中最重要的方法就是createBean,其中包含了Bean的依赖注入、初始化前、初始化、初始化后等

概念

BeanPostProcessor的缓存

spring中有很多类型BeanPostProcessor的子接口,spring会将这些子接口根据类型缓存,调用时直接从缓存中拿到然后遍历
省去了多次去找BeanPostProcessor的实现类。所谓的缓存应该就是一个Map或者List直接存在内存中

InstantiationAwareBeanPostProcessor
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}

	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}

	@Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {return null;}

	@Deprecated
	@Nullable
	default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}
}

BeanPostProcessor的子接口,调用时机是Bean实例化前,如果定义了这个接口的实现类,spring会在实例化Bean之前去调用实现类中的postProcessBeforeInstantiation方法
这个方法的参数是Class类型,因为此时Bean还没有被实例化,在这个方法中你可以用自己的逻辑去实例化Bean,将实例化后的Bean返回,以此来替代spring的实例化逻辑 。
这里可以做很多事,甚至你可以在创建UserService时直接返回个OrderService

注意:如果定义了多个InstantiationAwareBeanPostProcessor的实现类,会循环执行,但是实例化应该只有一次,所以如果执行到某一个processor时返回了对象,则不再执行后面的processor

MergedBeanDefinitionPostProcessor接口
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

	default void resetBeanDefinition(String beanName) {}
}

在Bean实例化之后处理,主要是对RootBeanDefinition的属性进行操作

createBean方法代码

此时类还没有被实例化,所以RootBeanDefinition中的class属性的值是String,即类名,实例化后就会被赋值为Class类型

  • 加载类,其中就会根据RootBeanDefinition的class属性判断是否已经加载,还会去选择类加载器,最终返回Class对象
  • 处理InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法
  • 如果InstantiationAwareBeanPostProcessor接口的逻辑没有返回对象,则去调用doCreateBean方法去创建对象
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){

	RootBeanDefinition mbdToUse = mbd;
	// 1:加载类
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		//设置class属性
		mbdToUse.setBeanClass(resolvedClass);
	}
	// 处理@LookUp注解
	mbdToUse.prepareMethodOverrides();

	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
	// 2:处理InstantiationAwareBeanPostProcessor接口
	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
	//如果InstantiationAwareBeanPostProcessor接口的逻辑返回了对象,则直接使用返回的对象,不再执行后面的操作
	if (bean != null) {
		return bean;
	}
	
	//3:doCreateBean方法中去实例化
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	return beanInstance;
}
doCreateBean方法
  • 实例化Bean,其中包含了对@Bean的处理、推断构造方法,经过这一步Bean已经被实例化了,但是没有属性
  • 处理MergedBeanDefinitionPostProcessors.postProcessMergedBeanDefinition()方法
    主要是对RootBeanDefinition的属性做操作,比如指定初始化方法等,指定初始化方法后,该方法会在初始化时执行
  • 循环依赖相关
  • 属性填充
    1. 处理InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 在这里可以自己进行依赖注入,注入后spring不会对该属性做处理
    2. 处理spring自带的依赖注入,理解为不使用@Autowire、@Resource而是使用by_name by_type进行依赖注入,常在xml中注入Bean时使用
    3. 调用InstantiationAwareBeanPostProcessor.postProcessProperties() 去处理@Autowire、@Resource、@Value,进行依赖注入
      经过这一步,对象已经有属性了
  • 初始化
    1. 初始化前,处理BeanPostProcessor.postProcessBeforeInitialization()方法
    2. 执行初始化方法,就是RootBeanDefinition中指定的初始化方法
    3. 初始化后,处理BeanPostProcessor.postProcessAfterInitialization()方法,也是AOP主要实现的位置
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		// 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	//判断该Bean是不是在Spring启动时就已经创建好了,如果已经创建就直接拿(主要针对FactoryBean)
	if (instanceWrapper == null) {
		// 1:实例化Bean,其中包含了对@Bean的处理、推断构造方法
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}
	// 后置处理合并后的BeanDefinition
	// 2:处理MergedBeanDefinitionPostProcessors接口的逻辑,
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			mbd.postProcessed = true;
		}
	}
	//3:循环依赖相关
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));

	// Initialize the bean instance.
	Object exposedObject = bean;
	// 4:属性填充
	populateBean(beanName, mbd, instanceWrapper);
	// 5:初始化
	exposedObject = initializeBean(beanName, exposedObject, mbd);
	return exposedObject;
}
createBean方法总结
createBean{
	1:加载类
	2:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 可以在此自己定义实例化规则,如果返回对象,则不做后面的处理了
	3:doCreateBean(){
		1:实例化Bean,经过这一步,就有对象了,但是对象属性没有值
		2:处理MergedBeanDefinitionPostProcessors.postProcessMergedBeanDefinition()方法  主要是对RootBeanDefinition的属性做操作,比如指定初始化方法等
		3:属性填充populateBean(){  
			1:处理InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()  此时对象已经实例化但是没有属性,在此方法中可以自己进行依赖注入
			2:处理spring自带的依赖注入
			3:调用InstantiationAwareBeanPostProcessor.postProcessProperties() 去处理@Autowire、@Resource、@Value.经过这一步,对象已经有属性了
		}
		4:初始化initializeBean(){
			1:初始化前,处理BeanPostProcessor.postProcessBeforeInitialization()方法
			2:执行初始化方法,就是RootBeanDefinition中指定的初始化方法
			3:初始化后,处理BeanPostProcessor.postProcessAfterInitialization()方法,也是AOP主要实现的位置
		}
	}
}

拓展

  • 父容器
    spring可以有父容器,源码中有很多内容都是如果本容器中找不到,就去父容器中找的代码

  • @DependsOn注解

@Component
@DependsOn("orderService")
public class UserService{}

表示userService依赖于orderService,创建userService之前要先创建orderService,和@Autowire作用相同,但底层实现不同
由@DependsOn注解引起的循环依赖是无法解决的,会直接报错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值