Spring创建Bean实例流程介绍

Spring创建Bean实例分析

文章主要讲解Spring的createBean方法,createBean之前一些操作就不介绍了。抛开Spring来说Java里面创建一个对象分成以下两个步骤:

  • Object object = new Object(); 创建一个对象(这时候object对象在Java堆中是已经分配了内存空间
  • 对这个对象进行属性赋值

带着这个思路我们去看下Spring是如何去创建Bean实例的,阅读的代码入口如下:

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

	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
	    // 我们从这里开始看了
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}
    /****************省略 ****************/
    /****************省略 ****************/
    /****************省略 ****************/   
}

1、Spring createBeanInstance

createBeanInstance看英文名大概知道是什么意思。这个方法主要功能是根据BeanDefinion对象去创建一个Bean(换句话说就是根据BeanDefinion反射去创建一个对象)

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
	instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
    // 我们从这里开始看起,转到代码定义
	instanceWrapper = createBeanInstance(beanName, mbd, args);
}

1、判断BeanDefinion对象是否有FactoryMethodName属性,然后根据FactoryMethod来创建实例,创建好直接返回实列(这个时候在JVM堆中已经存在对象了),代码如下:

if (mbd.getFactoryMethodName() != null) {
	return instantiateUsingFactoryMethod(beanName, mbd, args);
}

2、如果BeanDefinion没有FactoryMethodName属性,就会调用determineConstructorsFromBeanPostProcessors 方法收集有@Autowried注解的构造方法,如果存在此类的构造方法反射来创建一个bean实例

// 这个方法主要是收集存在@Autowried注解的构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
		mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
	// 然后把构造方法里面的引用参数类型进行注入,那下面的案例来说,这行代码最终会通过beanFactory.getBean(beanName) 得到一个bean注入到这个构造方法里面去
	return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
	return autowireConstructor(beanName, mbd, ctors, null);
}

3、@Autowried构造方法里面的参数是调用 autowireConstructor()方法注入进入的(它的后面还是调用了**beanFactory.getBean(beanName)**操作,代码太深了我贴一些关键步骤的代码 。有兴趣的可以按照以下的代码跟进去看看 )


// 1、ctors 参数注入
protected BeanWrapper autowireConstructor(
		String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

	return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}

// 2、构造ctors构造方法参数, 我们主要看 **createArgumentArray**
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
	try {
		String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
		if (paramNames == null) {
			ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
			if (pnd != null) {
				paramNames = pnd.getParameterNames(candidate);
			}
		}
		// 获取注入的参数,我们主要看这个方法
		argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
				getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
	}
	catch (UnsatisfiedDependencyException ex) {
		if (logger.isTraceEnabled()) {
			logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
		}
		// Swallow and try next constructor.
		if (causes == null) {
			causes = new LinkedList<>();
		}
		causes.add(ex);
		continue;
	}
}
else {
	// Explicit arguments given -> arguments length must match exactly.
	if (paramTypes.length != explicitArgs.length) {
		continue;
	}
	argsHolder = new ArgumentsHolder(explicitArgs);
}

// 3、这个方法太深了,直截取关键部分代码出来
try {
    // 主要看resolveAutowiredArgument方法
	Object autowiredArgument = resolveAutowiredArgument(
			methodParam, beanName, autowiredBeanNames, converter, fallback);
	args.rawArguments[paramIndex] = autowiredArgument;
	args.arguments[paramIndex] = autowiredArgument;
	args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
	args.resolveNecessary = true;
}
catch (BeansException ex) {
	throw new UnsatisfiedDependencyException(
			mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}

// 4、转到resolveAutowriedArgument这个方法 ,看主要的代码 
try {
	return this.beanFactory.resolveDependency(
			new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}
catch (NoUniqueBeanDefinitionException ex) {
	throw ex;
}

// 5、这个方法看 **doResolveDependency** ,这个方法站到定义
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	if (Optional.class == descriptor.getDependencyType()) {
		return createOptionalDependency(descriptor, requestingBeanName);
	}
	else if (ObjectFactory.class == descriptor.getDependencyType() ||
			ObjectProvider.class == descriptor.getDependencyType()) {
		return new DependencyObjectProvider(descriptor, requestingBeanName);
	}
	else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
		return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

// 6、 **descriptor.resolveCandidate** 这个方法转到定义
if (autowiredBeanNames != null) {
	autowiredBeanNames.add(autowiredBeanName);
}
// 如果这个参数是一个class 引用类型参数,就会执行这段代码的
if (instanceCandidate instanceof Class) {
	instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
	if (isRequired(descriptor)) {
		raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
	}
	result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
	throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;

// 7、继续跟进去你就会发现最终调用的是beanFactory.getBean(beanName) 操作
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
		throws BeansException {
    // 最后还是会调用getBean获取实例
	return beanFactory.getBean(beanName);
}

4、绝大部分操作都会采用无参函数的实例化的,无参构造代码就比较好理解,代码如下:

// 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);

小结:这个时候一个对象已经创建好了,在JVM堆中已经存在了,但是这个bean是一个半成品 。因为这个bean里面的很多属性没有做依赖注入。我们要对一个bean做依赖注入,首先我们通过反射来获取有 @Autowried、@Resource、@PostConstructor、@PreDestory 注解的方法 和 属性信息

2、Spring 收集Metadata

上面我们介绍了 spring创建bean,但是这个bean是一个半成品,因为这个bean还没有做依赖注入。要做依赖注入之前我们是不是先要把需要注入的信息收集起来 ,接下来我们介绍 applyMergedBeanDefinitionPostProcessors这个方法

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof MergedBeanDefinitionPostProcessor) {
			MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
			bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
		}
	}
}

这个MergedBeanDefinitionPostProcessor是一个接口,我们看下相关的实现类

在这里插入图片描述

扫描二维码关注公众号,回复: 10232069 查看本文章

CommonAnnotationBeanPostProcessor

1、我们先来看下CommonAnnotationBeanPostProcessor这个实现类 ,看这个实现类之前我先把这个类的无参构造方法

// 我插累,这里面有PostConstruct 和 PreDestroy ,转到定义两个注解
public CommonAnnotationBeanPostProcessor() {
	setOrder(Ordered.LOWEST_PRECEDENCE - 3);
	setInitAnnotationType(PostConstruct.class);
	setDestroyAnnotationType(PreDestroy.class);
	ignoreResourceType("javax.xml.ws.WebServiceContext");
}

// 这个方法就是通过反射收集 @PostConstruct 、@PreDestroy 、@Resource 注解的信息
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    // 这个方法就是通过反射收集 @PostConstruct 、@PreDestroy 注解 方法信息
	super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
	// 这个方法也是通过放射收集 @Resource 注解的 字段信息、方法信息 
	InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}

2、CommonAnnotationBeanPostProcessor -> postProcessMergedBeanDefinition 主要以下几件事

  • 收集了有@PostConstruct 、@PreDestroy 注解的方法信息 ,并把它包装成 LifecycleMetadata 对象存入到lifecycleMetadataCache 这个Map里面
  • 收集了有@Resource 注解的方法、字段信息,并把它包装成InjectionMetadata对象存入到 injectionMetadataCache 这个Map里面
  • 这个收集代码就不贴出来了,本人是一个小白都能看得懂,挺简单的

AutowiredAnnotationBeanPostProcessor

1、接下来我们来看下AutowiredAnnotationBeanPostProcessor实现类,我们同样来看下无参构造方法。


// 出现了 Autowired 注解 和 Value 注解 ,把它存入到 autowiredAnnotationTypes里面去了,这个记住以下,后面收集的时候需要用的到这个变量
public AutowiredAnnotationBeanPostProcessor() {
	this.autowiredAnnotationTypes.add(Autowired.class);
	this.autowiredAnnotationTypes.add(Value.class);
	try {
		this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
				ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
		logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
	}
	catch (ClassNotFoundException ex) {
		// JSR-330 API not available - simply skip.
	}
}

// 这个方法来收集有@Autowired  方法和字段信息
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    // 这个方法也是通过放射收集 @Autowired 注解的 字段信息、方法信息
	InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}

总结: 收集了有 @Autowired 注解的方法、字段信息,并把它包装成InjectionMetadata对象存入到 injectionMetadataCache 这个Map里面( 这些代码容易理解,没啥逻辑的所以不贴出来了

3、Spring populateBean 依赖注入


// 这个方法先不去了解
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));
}

循环依赖注入这里不讲解了,所以这个方法先不看了,我们直接看 populateBean 方法 ,这个方法就是DI 核心注入方法

// Initialize the bean instance.
Object exposedObject = bean;
try {
    // 这个方法就是DI 核心注入方法
	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);
	}
}

1、转到populateBean方法,我们先来阅读一段很有意思的代码

// 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.
boolean continueWithPropertyPopulation = true;

// 这段代码很有意思,写一个InstantiationAwareBeanPostProcessor接口实现类,可以让所有的bean不能依赖注入
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
			    // 是否需要依赖注入
				continueWithPropertyPopulation = false;
				break;
			}
		}
	}
}

// 如果不需要直接return了
if (!continueWithPropertyPopulation) {
	return;
}

// 这里我不多说了,那些想搞破坏的同志们....... 

if (hasInstAwareBpps) {
	if (pvs == null) {
		pvs = mbd.getPropertyValues();
	}
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;			// 依赖注入过程, @Autowired的支持
			PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
			if (pvsToUse == null) {
				if (filteredPds == null) {
					filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
				}
			    // 老版本spring用这个方法完成依赖注入, @Autowired的支持
				pvsToUse = ibp.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);
}

// 老版本用 <property name="username" value="Jack" />
// 标签做依赖注入,复杂且无用
if (pvs != null) {
	applyPropertyValues(beanName, mbd, bw, pvs);
}

2、我们直接看这段代码 postProcessProperties 这个方法 ,InstantiationAwareBeanPostProcessor 是一个接口,我们来看下接口实现类

在这里插入图片描述
3、我们先来看AutowiredAnnotationBeanPostProcessor 这个类的 postProcessProperties 方法


public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 看到这个对象是不是很熟悉,上面刚介绍过的,调用postProcessMergedBeanDefinition收集需要注入的信息
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
	    //这一段转到定义,你就会发现他是一个一个循环,然后反射赋值
		metadata.inject(bean, beanName, pvs);
	}
	catch (BeanCreationException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
	}
	return pvs;
}

// 循环注入
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
			(checkedElements != null ? checkedElements : this.injectedElements);
	if (!elementsToIterate.isEmpty()) {
	    // 循环injectElements
		for (InjectedElement element : elementsToIterate) {
			if (logger.isTraceEnabled()) {
				logger.trace("Processing injected element of bean '" + beanName + "': " + element);
			}
			// 我们在转到定义去看看这个
			element.inject(target, beanName, pvs);
		}
	}
}

// 用过反射的就看的出来,这里面反射赋值
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Field field = (Field) this.member;
	Object value;
	if (this.cached) {
		value = resolvedCachedArgument(beanName, this.cachedFieldValue);
	}
	else {
		DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
		desc.setContainingClass(bean.getClass());
		Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
		Assert.state(beanFactory != null, "No BeanFactory available");
		TypeConverter typeConverter = beanFactory.getTypeConverter();
		try {
		    // 这个需要注入的bean 最终还是通过beanFactory.getBean() 去获取的
			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
		}
		synchronized (this) {
			if (!this.cached) {
				if (value != null || this.required) {
					this.cachedFieldValue = desc;
					registerDependentBeans(beanName, autowiredBeanNames);
					if (autowiredBeanNames.size() == 1) {
						String autowiredBeanName = autowiredBeanNames.iterator().next();
						if (beanFactory.containsBean(autowiredBeanName) &&
								beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
							this.cachedFieldValue = new ShortcutDependencyDescriptor(
									desc, autowiredBeanName, field.getType());
						}
					}
				}
				else {
					this.cachedFieldValue = null;
				}
				this.cached = true;
			}
		}
	}
	//如果value有值,就反射field.set赋值
	if (value != null) {
		ReflectionUtils.makeAccessible(field);
		field.set(bean, value);
	}
}

4、上面inject 方法如果简单的说只做了两件事 :

  • 通过beanFactory.getBean(beanName) 获取需要注入的bean对象
  • 得到注入的bean对象后,通过反射赋值
  • 其它的就不一一列举了,流程度差不多

4、Spring initializeBean后置操作

当一个bean在spring容器中完成了创建和依赖注入,这个bean就标识可以使用了。但是spring还定义了一些接口比如:BeanFactoryAware、InitializingBean 接口及@PostConstruct注解的方法

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
	    //1 、调用 Aware方法
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
	    // 2、对bean中的特殊方法的调用,比如@PostConstruct、Aware接口的方法调用
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
	    // 2、InitializingBean 接口, afterPropertiesSet ,init-method属性调用 
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
	    // 3、这个是AOP的切入点,这里不详细介绍 。。。。。 
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

总结

Spring 的doCreateBean 操作流程如下:

  • 通过 createBeanInstance 创建bean 实例(这个bean对象还是一个半成品,需要做依赖注入的属性都还没有注入
  • 通过 MergedBeanDefinitionPostProcessor -> postProcessMergedBeanDefinition 来收集bean需要注入的(方法、属性)并且封装成Metadata对象存入缓存中
  • 通过 InstantiationAwareBeanPostProcessor -> postProcessProperties 方法来循环注入相应的bean实例(这里需要补充一句,需要注入的对象也是通过beanFactory.getBean(beanName)去获取的,得到bean实例后,在通过反射方式赋值给目标对象
  • 最后还是要说一句,本人也是小白。博客上很多关于spring的优秀文章,本人就是为了加深理解,就在这里抛砖引玉。
发布了16 篇原创文章 · 获赞 10 · 访问量 7950

猜你喜欢

转载自blog.csdn.net/mnicsm/article/details/103685087