前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【小家Spring】AbstractBeanFactory#getBean()、doGetBean完成Bean的初始化、实例化,以及BeanPostProcessor后置处理器源码级详细分析

【小家Spring】AbstractBeanFactory#getBean()、doGetBean完成Bean的初始化、实例化,以及BeanPostProcessor后置处理器源码级详细分析

作者头像
YourBatman
发布2019-09-03 16:50:02
1.7K0
发布2019-09-03 16:50:02
举报
文章被收录于专栏:BAT的乌托邦BAT的乌托邦

前言

这边博文,主要讲解我们Spring IOC容器的主菜:Bean的实例化、初始化。

通过之前跟踪Spring IOC刷新的源码,我们所有的剩余的单例Bean都是通过这一步:finishBeanFactoryInitialization(beanFactory);来进行初始化的。最重要的一个方法就为:DefaultListableBeanFactory#preInstantiateSingletons

其内部核心方法为:getBean --> doGetBean方法

Spring源码基于的Spring版本为:5.0.6.RELEASE(下同) Spring源码基于的Spring版本为:5.0.6.RELEASE(下同) Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)

getBean方法概述

getBean()是顶层接口BeanFactory提供的,一共有五个原型:

代码语言:javascript
复制
Object getBean(String name) throws BeansException;
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
// Spring2.5以后才有的接口
Object getBean(String name, Object... args) throws BeansException;
// Spring3.0以后才有的接口
<T> T getBean(Class<T> requiredType) throws BeansException;
// Spring4.1以后才有的接口
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

说明:很多人都不理解这个args是干什么用的,这里解释一下。首先我们要明白,getBean()内部不仅仅是get,如果get不到还可能去实例化一个Bean的(默认根据空构造函数进行实例化),因此本处的args其实就是为了匹配构造函数而提供的扩展功能~

使用前提: 1、传入的参数必须有相对应的构造函数入参与之匹配 2、bean的scope必须设置成prototype,因为动态传参话bean不可以是单例的

AbstractBeanFactory作为抽象实现,复写了其中3个方法:

代码语言:javascript
复制
	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	@Override
	public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}
	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		return doGetBean(name, null, args, false);
	}
// 备注:此处的doGetBean,就是Bean实例化的核心逻辑

DefaultListableBeanFactory继承自AbstractBeanFactory,复写了剩余的2个方法:

代码语言:javascript
复制
	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		return getBean(requiredType, (Object[]) null);
	}
	// 上面那个方法是调用这个方法的逻辑。
	@Override
	public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {]
		// resolveNamedBean里面的逻辑,也是根据requiredType去找的。若不止一个会抛错:NoUniqueBeanDefinitionException
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}

		// 从这里我们可以看到,如果子容器里没有找到Bean,还回去父容器(若存在的话)里找找看
		BeanFactory parent = getParentBeanFactory();
		if (parent != null) {
			return (args != null ? parent.getBean(requiredType, args) : parent.getBean(requiredType));
		}
		throw new NoSuchBeanDefinitionException(requiredType);
	}

那么接下里,我们就得看看这里面最最核心的逻辑:doGetBean()

AbstractBeanFactory#doGetBean

依赖注入主要有两个过程,一个是实例化Bean,另一个是将依赖关系注入到Bean中

从命名上我们也可以看出:他是doGetBean,是有do这个动作的。因此不是简单的get有就返回,没有就返回null这么简单的操作。而是里面做了实例化、依赖注入、属性赋值、解决循环依赖等一些列操作~

先贴上源码(本方法源码不可为不长,超过150行):

代码语言:javascript
复制
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		// 该方法作用:1、 如果是FactoryBean,会去掉Bean开头的&符号
		// 2、能存在传入别名且别名存在多重映射的情况,这里会返回最终的名字,如存在多层别名映射A->B->C->D,传入D,最终会返回A
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// getSingleton()方法的实现,在父类DefaultSingletonBeanRegistry中,请先移步下面,看详解
		//这里先尝试从缓存中获取,若获取不到,就走下面的创建
		// 特别注意的是:这里面走创建(发现是个new的),就加入进缓存里面了 if (newSingleton) {addSingleton(beanName, singletonObject);}   缓存的字段为全局的Map:singletonObjects
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				// 这里虽然只是一句日志,但是能说明用意。
				// 若条件为true,表示这个Bean虽然在缓存里,但是还并没有完全被初始化(循环引用)
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				} else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}

			// 在getBean方法中,getObjectForBeanInstance是个频繁使用的方法。因此为了更好的知道细节,下面会详解这个方法的
			// 其实简单理解就是处理FactoryBean的getObject()方法
			bean = 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);
			}

			// Check if bean definition exists in this factory.
			// 这一步也是必须要做的,若存在父容器,得看看父容器是否实例化过它了。避免被重复实例化(若父容器被实例化,就以父容器的为准)
			// 这就是为何,我们扫描controller,哪怕不加排除什么的,也不会出问题的原因~,因为Spring中的单例Bean只会被实例化一次(即使父子容器都扫描了)
			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 {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}
			
			//alreadyCreated字段增加此值。表示此Bean已经创建了
			// 备注,此处我们就以 `helloServiceImpl` 这个Bean的创建为例了~~~
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				// 根据名字获取合并过的对应的RootBeanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 检查mbd是否为抽象的或mbd为单例,但存在args的情况(args只有初始化原型对象才允许存在)
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 这里就重要了,因为我们会有属性注入等等  所以这里就是要保证它依赖的那些属性先初始化才行
				// 这部分是处理循环依赖的核心,这里稍微放一放。下面有大篇幅专门讲解这方面的以及原理解决方案
				// @DependsOn注解可以控制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);
						}
					}
				}

				// Create bean instance.
				// 从这里开始,就正式开始着手创建这个Bean的实例了~~~~
				if (mbd.isSingleton()) {
					
					// 也是一样先尝试从缓存去获取,获取失败就通过ObjectFactory的createBean方法创建
					// 这个getSingleton方法和上面是重载方法,它支持通过ObjectFactory去根据Scope来创建对象,具体源码解析见下面
					sharedInstance = getSingleton(beanName, () -> {
						try {

							// 这是创建Bean的核心方法,非常重要~~~~~~~~~~~~~~~下面会有
							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.
							// 执行失败,就销毁Bean。然后执行对应的destroy方法,等等销毁Bean时候的生命周期方法们~~~~~~~~~这个就不多说了   主要看看上面的createBean方法吧
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				} 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);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final 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);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		// 这里就比较简单了,就是requiredType,比如要求是Integer,获得的是String,俺么就会调用转换器转换过来
		// 绝大多数情况下,没啥卵用
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			} catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

DefaultSingletonBeanRegistry#getSingleton**详解**:

代码语言:javascript
复制
	@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}

	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 此处是先从已经缓存好了的singletonObjects的Map中,查看有木有(至于当前已经有哪些了,下面有个截图,相信什么时候进来的都应该有些印象吧)
		Object singletonObject = this.singletonObjects.get(beanName);

		// 若缓存里没有。并且,并且,并且这个Bean必须在创建中,才会进来。
		// singletonsCurrentlyInCreation字段含义:会缓存下来所有的正在创建中的Bean,如果有Bean是循环引用的  会把这种Bean先放进去,这里才会有值
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

DefaultSingletonBeanRegistry#getSingleton**详解(根据ObjectFactory结合Scope来创建合适的对象)**:

代码语言:javascript
复制
	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) {
			
				// 如果这个Bean正在被销毁,就抛异常了
				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!)");
				}
				// 创建前置检查:1、若在inCreationCheckExclusions面校验名单里,是ok的
				//2、singletonsCurrentlyInCreation把它添加进去,证明这个Bean正在创建中
				beforeSingletonCreation(beanName);
				// 此处先打标机为为false
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 把这个实例生成出来,并且标志位设为true
					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.
					// in the meantime再次旗舰,若有人已经把这个Bean放进去了,那就抛出这个异常吧
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				} catch (BeanCreationException ex) {
					// 处理异常
					// 比如我们经常遇到的UnsatisfiedDependencyException异常:@Autowired的时候找不到依赖的Bean就是这个异常(一般由NoSuchBeanDefinitionException这个异常导致)
					// 这里会吧异常链接拼接起来,然后一起打印出来~~~~非常方便查找问题
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				} finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					// 创建完成后再检查一遍。做的操作为:从正在创建缓存中移除
					afterSingletonCreation(beanName);
				}
				
				// 这里也非常重要:若是新的Bean,那就执行addSingleton这个方法,这个方法做了什么,就下面4步操作:
				//this.singletonObjects.put(beanName, singletonObject); //缓存起来
				//this.singletonFactories.remove(beanName); //把对应ObjectFactory的缓存移除
				//this.earlySingletonObjects.remove(beanName);
				//this.registeredSingletons.add(beanName);
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

开始创建Bean AbstractAutowireCapableBeanFactory#createBean 提供此方法的抽象类为:AbstractBeanFactory,由子类去实现创建的逻辑。


代码语言:javascript
复制
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		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.
		// 确保对应BeanClass完成解析(已经加载进来了Class对象)具体表现是进行了ClassLoder.loadClass或Class.forName完成了类加载
		// 主要根据传入的typesToMatch生成特定的ClassLoader,之后还要调用RootBeanDefinition#resolveBeanClass,根据特定的加载器或者默认加载器加载出class属性对应的Class对象
		// 我们这里解析出来,显然就是class com.fsx.service.HelloServiceImpl这个Class了
		// 判断需要创建的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 {
			// 这里主要是解析<lookup-method name="getFruit" bean="bananer"/>类似这种方式的依赖注入(Spring支持lookup-method,replace-method两个依赖注入的方式)
			// 它相当于调用指定类里面的指定方法进行注入,所以需要考虑到方法重载的情况,因此这个方法解析的就是这种情况
			// 由于项目中一般这么使用,也非常的不大众,具体原理此处省略
			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.
			// 从doc解释:给BeanPostProcessors一个机会来返回一个代理对象代替目标对象   什么动态代理之类的,都在这里实现的~~~~~~~~~~~~~~~~~~~
			// 1、具体逻辑是判断当前Spring容器是否注册了实现了InstantiationAwareBeanPostProcessor接口的后置处理器如果有,则依次调用其中的applyBeanPostProcessorsBeforeInstantiation方法,如果中间任意一个方法返回不为null,直接结束调用。
			// 2、然后依次所有注册的BeanPostProcessor的postProcessAfterInitialization方法(同样如果任意一次返回不为null,即终止调用。
			// 这个方法也非常的重要,后续有详细讲解
			
			// 容器里所有的InstantiationAwareBeanPostProcessors实例,都会在此处生效,进行前置处理~~~~~~~~~~
			// 下面有解释:BeanPostProcessor和InstantiationAwareBeanPostProcessor的区别,可以分清楚他们执行的时机
			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);
		}

		// 这里又是一个核心逻辑:doCreateBean 创建Bean
		try {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			// 创建完成后 直接短路掉返回 
			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);
		}
	}

resolveBeforeInstantiation详解:


代码语言:javascript
复制
	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		// beforeInstantiationResolved 这个属性如果是false,表示不需要被前置处理了
		// 然后,唯一能改变它的值的地方,是下面这仅仅一行代码而已,它的访问权限为package
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			// 这里hasInstantiationAwareBeanPostProcessors()方法就是看属性hasInstantiationAwareBeanPostProcessors的值。就是标记容器里是否有InstantiationAwareBeanPostProcessor的实现
			// 显然,在执行addBeanPostProcessor,发现这个Bean是这个子类型的时候,就会设为true了。同理的还有hasDestructionAwareBeanPostProcessors这个属性,表示销毁的处理器
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				
				// 拿到最终的目标类型(放置被别的包装过)显然此处是;com.fsx.service.HelloServiceImpl
				// 可能依赖于AbstractBeanFactory#resolveBeanClass这个方法去解析
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					// 先执行执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation回调方法  
					// 里面的逻辑也比较简单:拿到缓存好的(List装着的)所有的BeanPostProcessors,如果是InstantiationAwareBeanPostProcessor就执行吧~~
					// 只要有一个result不为null;后面的所有 后置处理器的方法就不执行了,直接返回(所以执行顺序很重要)
					//1、ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor这个内部类就是这个类型。主要还是去增强、完善处理@Configuration这种类   但是它并没有重写postProcessBeforeInstantiation这个方法,所以默认是返回null的
					//2、CommonAnnotationBeanPostProcessor/Autowired。。。也没做处理(若你自己不去注册,那系统里就再没有了)
					// 需要注意的是,如果我们采用了AOP、声明式事务等等,这里就会有了,后面又会回来讲解这一块
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				
					// 我们可以看到,如果bean不为null,那就直接返回了  短路掉后面的After也就不执行了
					if (bean != null) {
						// 注意,这里是Initialization,是初始化的后置方法,是BeanPostProcessor的方法,也就是说初始化完成后的方法。
						// 为何这里执行这个方法呢?是因为我们上面说了,如果返回不为null,后面都都会被短路掉。但是此处Spring还是让我们执行了初始化后的处理器方法,这点需要引起注意
						// 就是说:即使Bean在实例化前已经返回了一个不为null的对象,别的方法都被短路了,但是我的【初始化】后处理器方法applyBeanPostProcessorsAfterInitializationh还是可以执行的
						// 这里面可以关注一下这个类:ApplicationListenerDetector
						//初始化之后的方法返回了null,那就需要调用doCreateBean生成对象了==============
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
BeanPostProcessorInstantiationAwareBeanPostProcessorSmartInstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor

这两个接口,是比较容易搞混的,需要这里注意区分一下。InstantiationAwareBeanPostProcessor代表了Spring的另外一段生命周期:实例化。先区别一下Spring Bean的实例化和初始化两个阶段的主要作用:

  • 实例化:实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中
  • 初始化:初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性

所以现在就清楚了:InstantiationAwareBeanPostProcessor是作用于 实例化 前后,所以是先执行的。BeanPostProcessor是作用于 初始化 前后,给Bean各个属性赋值的时候执行的(比如我们的属性依赖注入,都是这个时候生效的)

BeanPostProcessor中的方法是初始化类时候的处理器(实例化早于初始化)在spring中初始化指的一般是在调用init-method属性前后

代码语言:javascript
复制
// 咋一看,以为方法名都一样?哈哈  其实你区分出来两个单词的意思,就明白了
// Instantiation:[ɪnstænʃɪ'eɪʃən] 实例化,例示
// Initialization:[ɪˌnɪʃəlaɪ'zeɪʃn] 初始化,设定初始值

public interface BeanPostProcessor {
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}
子接口: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 postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		return pvs;
	}
}

内部类:BeanPostProcessorCheckersh实现了postProcessAfterInitialization方法:输出了一行日志而已

ApplicationListenerDetector重点实现了postProcessAfterInitialization方法:测那些实现了接口ApplicationListener的bean,在它们创建时初始化之后,将它们添加到应用上下文的事件多播器上。并在这些ApplicationListener bean销毁之前,将它们从应用上下文的事件多播器上移除。

子接口:SmartInstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor 继承自 InstantiationAwareBeanPostProcessor;

但是SmartInstantiationAwareBeanPostProcessor多了一个三个方法

代码语言:javascript
复制
// 从名字上,它有个Smart,是比较智能一些的
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
	// 预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null
	@Nullable
	default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}
	// 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器
	// beanClass参数表示目标实例的类型,beanName是目标实例在Spring容器中的name
	// 返回值是个构造器数组,如果返回null,会执行下一个PostProcessor的determineCandidateConstructors方法;否则选取该PostProcessor选择的构造器
	@Nullable
	default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
			throws BeansException {

		return null;
	}
	// 获得提前暴露的bean引用。主要用于解决循环引用的问题
	// 只有单例对象才会调用此方法
	// 在我们准们处理讲解循环引用的时候,这个方法会起到比较关键的作用
	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

这个接口有什么作用的呢?这里举例两个实现,有个感觉就行:

比如AutowiredAnnotationBeanPostProcessor:依赖注入时的泛型依赖注入,就通过这个能智能判断类型来注入。

泛型依赖注入的优点:允许我们在使用spring进行依赖注入的同时,利用泛型的优点对代码进行精简,将可重复使用的代码全部放到一个类之中,方便以后的维护和修改。比如常用的Base设计。。。(属于Spring 4.0的新特性)

Spring4.0之后,这样是不报错的:

代码语言:javascript
复制
@Configuration
public class MyConfiguration {
	@Bean
	public BaseRepository<Student> studentRepository() {
		return new BaseRepository<Student>() {};
	}
	
	@Bean
	public BaseRepository<Faculty> facultyRepository() {
		return new BaseRepository<Faculty>() {};
	}
}


// 注意,这里能够正确注入到正确的Bean,虽然他们都是BaseRepository类型。但是在Spring4.0之后,泛型里面的东西
// 也可以作为一种分类Qualifier,随意这里虽然都是BaseRepositor类型,但是在容器中还是被分开了的
@Autowired private BaseRepository<Student> studentRepo; 
@Autowired private BaseRepository<Faculty> facultyRepo;

另外Spring-AOP包下有很多实现,比如我们最熟悉的:AnnotationAwareAspectJAutoProxyCreator等等这种类,具体我们在AOP分析的时候再详解

子类MergedBeanDefinitionPostProcessor
代码语言:javascript
复制
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
	//来给后续回调中缓存一些meta信息使用
	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}

用来将merged BeanDefinition暴露出来的回调。看看它的一些主要实现:

代码语言:javascript
复制
//InitDestroyAnnotationBeanPostProcessor
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
		metadata.checkConfigMembers(beanDefinition);
	}

//CommonAnnotationBeanPostProcessor
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

//AutowiredAnnotationBeanPostProcessor
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

//ApplicationListenerDetector
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		this.singletonNames.put(beanName, beanDefinition.isSingleton());
	}

稍微总结下:

  1. InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置
  2. postProcessBeforeInstantiation方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
  3. postProcessAfterInstantiation方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行
  4. postProcessPropertyValues方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改
  5. 父接口BeanPostProcessor的2个方法postProcessBeforeInitializationpostProcessAfterInitialization都是在目标对象被实例化之后,并且属性也被设置之后调用的

Instantiation表示实例化,Initialization表示初始化。实例化的意思在对象还未生成,初始化的意思在对象已经生成

创建Bean的最终方法,绝大多数Bean的实例化、初始化都会走这里:

AbstractAutowireCapableBeanFactory#doCreateBean

spring的ioc创建bean的最核心代码 我们来看看他具体做了啥 怎么做

讲解之前,贤了解下BeanWrapper吧:

BeanWrapper 是Spring提供的一个用来操作javaBean属性的工具,使用它可以直接修改一个对象的属性。

BeanWrapper大部分情况下是在spring ioc内部进行使用,通过BeanWrapper,spring ioc容器可以用统一的方式来访问bean的属性。用户很少需要直接使用BeanWrapper进行编程。

对于bean属性的操作,我们熟知的主要有下面这些工具类:

  1. Apache的BeanUtils和PropertyUtils
  2. cglib的BeanMap和BeanCopier
  3. spring的BeanUtils

Spring中BeanWrapper 的主要在于如下三点:

1· 支持设置嵌套属性

  1. 支持属性值的类型转换(设置ConversionService)
  2. 提供分析和操作标准JavaBean的操作:获取和设置属性值(单独或批量),获取属性描述符以及查询属性的可读性/可写性的能力
代码语言:javascript
复制
public interface BeanWrapper extends ConfigurablePropertyAccessor {
	 //为数组和集合自动增长指定一个限制。在普通的BeanWrapper上默认是无限的。
	void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
	//返回数组和集合自动增长的限制。
	int getAutoGrowCollectionLimit();
    //如果有的话,返回由此对象包装的bean实例
	Object getWrappedInstance();
	//返回被包装的JavaBean对象的类型。
	Class<?> getWrappedClass();
	//获取包装对象的PropertyDescriptors(由标准JavaBeans自省确定)。
	PropertyDescriptor[] getPropertyDescriptors();
	//获取包装对象的特定属性的属性描述符。
	PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
}

BeanWrapperImpl是Spring提供的唯一实现类。具体此处不深究了,知道它是Spring用来统一处理Bean的就成了

doCreateBean源码解析
代码语言:javascript
复制
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// 用BeanWrapper来持有创建出来的Bean对象
		BeanWrapper instanceWrapper = null;
		//如果是单例的话,则先把缓存中的同名bean清除(同名的)
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		//实际创建的交给createBeanInstance来完成,
		//bean的生成,这里会使用默认的类生成器,包装成BeanWrapperImpl类,为了下面的populateBean方法的属性注入做准备 
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		//如果不是NullBean,则将resolvedTargetType 属性设置为当前的WrappedClass
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					// 此处处理这个接口的处理器:MergedBeanDefinitionPostProcessor,他在BeanPostProcessor的基础上增加了postProcessMergedBeanDefinition方法,在此处就被调用了
					// 主要是处理@PostConstruct,@Autowire,@Value,@Resource,@PreDestory等这些注解。(显然对应哪去处理器,一目了然了) 下面会举例看看AutowiredAnnotationBeanPostProcessor的处理
					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.
		//如果当前bean是单例,且支持循环依赖,且当前bean正在创建,通过往singletonFactories添加一个objectFactory,这样后期如果有其他bean依赖该bean 可以从singletonFactories获取到bean
		//getEarlyBeanReference可以对返回的bean进行修改,这边目前除了可能会返回动态代理对象 其他的都是直接返回bean
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 这里面主要是解决循环引用问题~~~~~~~~~借助了这个工厂
			//这里主要是调用处理器:SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference方法去寻找到前期的Bean们(若存在这种处理器的话)
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		// 这个Obj,就是最终要返回的对象了
		Object exposedObject = bean;
		try {

			// 这又是非常非常重要的一步:给已经初始化的属性们赋值===================对bean进行填充,在这里面完成依赖注入的相关内容
			// 啥都不说了,看下面的详解吧
			populateBean(beanName, mbd, instanceWrapper);

			//完成属性依赖注入后,进一步初始化Bean  具体进行了以下操作:
			//若实现了BeanNameAware, BeanClassLoaderAware,BeanFactoryAwareAware等接口,则注入相关对象
			//遍历后置处理器,调用实现的postProcessBeforeInitialization方法,
			//如果实现了initialzingBean,调用实现的 afterPropertiesSet()
			//如果配置了init-mothod,调用相应的init方法
			//遍历后置处理器,调用实现的postProcessAfterInitialization

			// 关于populateBean和initializeBean的详解,下贴出了博文链接参考~~~~~~
			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);
			}
		}
		
		//如果earlySingletonExposure为true,尝试从缓存获取该bean(一般存放在singletonFactories对象通过调用getObject 把对象存入earlySingletonObjects),
		// 分别从singletonObjects和earlySingletonObjects获取对象   这里依然是处理循环依赖相关问题的
		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 " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			// 如果有需要,就注册DisposableBean,这样Bean销毁的时候此种后置处理器也会生效了
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		} catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

doCreateBean依赖的createBeanInstance 和 populateBean两个方法解释:

在 createBeanInstance 中生成了Bean所包含的java对象:

代码语言:javascript
复制
	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);
		//确保class不为空,并且访问权限为public  所以注意如果你的Class不是public的,Spring给你创建不了对象
		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());
		}

		// 配置的一种特殊的callback回调方法,通过这个callback创建bean
		// Supplier返回的Obj,最终会交给obtainFromSupplier包装成BeanWrapper 
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		
		// 这是Spring支持的又一种方式:使用工厂方法来进行bean的实例化
		if (mbd.getFactoryMethodName() != null)  {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
		// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
		// 此部分在循环依赖中,会有更深入的说明~~~~~~~~~~~~~~~~
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					// 标记一下,已经解析过class的构造器
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		// resolved若为true,表示已经解析过构造器了,就下面直接使用解析好的构造器实例化Bean
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

		// Need to determine the constructor...
		// 通过此方法,去检测到一个可用的构造器:这里面智能使用SmartInstantiationAwareBeanPostProcessor啦,它通过循环调用处理器的determineCandidateConstructors方法,谁第一个发现一个可用的构造器,就return,否则返回null
		// 详情见下面讲解AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors方法的讲解
		

		// 这里需要注意:如果你的Bean没有空的构造函数(比如只有一个参数的构造函数,那么Spring会用这个构造函数给你实例化Bean,并且入参会自动帮你从容器里去找出来)
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// No special handling: simply use no-arg constructor.
		return instantiateBean(beanName, mbd);
	}

AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors:检测出候选的构造器们(也就是我们常说的:构造器注入)

检测Bean的构造器,可以检测出多个候选构造器,再有相应的策略决定使用哪一个。它将将自动扫描通过**@Autowired/@Value**注解的构造器从而可以完成构造器注入

代码语言:javascript
复制
	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
			throws BeanCreationException {

		// Let's check for lookup methods here..
		// 检测@Lookup注解,这个注解的注入方式,已经不推荐使用了===========
		if (!this.lookupMethodsChecked.contains(beanName)) {
			try {
				ReflectionUtils.doWithMethods(beanClass, method -> {
					Lookup lookup = method.getAnnotation(Lookup.class);
					if (lookup != null) {
						Assert.state(beanFactory != null, "No BeanFactory available");
						LookupOverride override = new LookupOverride(method, lookup.value());
						try {
							RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
							mbd.getMethodOverrides().addOverride(override);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(beanName,
								"Cannot apply @Lookup to beans without corresponding bean definition");
						}
					}
				});
			}
			catch (IllegalStateException ex) {
				throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
			}
			this.lookupMethodsChecked.add(beanName);
		}

		// Quick check on the concurrent map first, with minimal locking.
		// 先从缓存里去看,有没有解析过此类的构造函数~~~
		////对每个类的构造函数只解析一次,解析完会存储结果,以备下次复用
		Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
		if (candidateConstructors == null) {
			// Fully synchronized resolution now...
			synchronized (this.candidateConstructorsCache) {
				
				// 为了线程安全,这里继续校验一次
				candidateConstructors = this.candidateConstructorsCache.get(beanClass);
				if (candidateConstructors == null) {
					Constructor<?>[] rawCandidates;
					try {
						// 拿到此Class所有的构造函数们(一般的类都只有一个空的构造函数)  当然我们也可以写多个
						rawCandidates = beanClass.getDeclaredConstructors();
					} catch (Throwable ex) {
						throw new BeanCreationException(beanName,
								"Resolution of declared constructors on bean Class [" + beanClass.getName() +
								"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
					}
					List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
					Constructor<?> requiredConstructor = null;
					Constructor<?> defaultConstructor = null;
					// 兼容Kotlin类型做的处理~~~~~~~~~~~~
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					int nonSyntheticConstructors = 0;
					// 遍历处理每个每个构造器~~~~~~~~~~~~~~~~~~
					for (Constructor<?> candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}

						// 找到构造器里有@Aotowaired或者@Value注解的直接信息们
						AnnotationAttributes ann = findAutowiredAnnotation(candidate);
						if (ann == null) {

							// 此方法的目的是拿到目标类:比如若是被cglib代理过的,那就拿到父类(因为cglib是通过子类的形式加强的)
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							// 说明确实是被CGLIB代理过的,那就再解析一次  看看父类是否有@Autowaired这种构造器
							if (userClass != beanClass) {
								try {
									Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								} catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}

						// 这里是是存在注解标注的这种构造器的
						if (ann != null) {

							// 这个判断很有必要,表示要求的构造器最多只能有一个
							//画外音:@Autowired标注的构造器数量最多只能有一个(当然,required=true的只能有一个,=false的可以有多个)
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}

							//获取autowire注解中required属性值
							boolean required = determineRequiredStatus(ann);
							// 只有是true,就往下走(默认值为true)
							if (required) {
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								// 这样子,这个构造器就是必须的了,记录下来
								requiredConstructor = candidate;
							}
							// 把标注有@Autowired注解的构造器,记录下来,作为候选的构造器
							candidates.add(candidate);
						}
						
						// 这个就重要了,处理精妙
						// 若该构造器没有被标注@Autowired注解,但是它是无参构造器,那就当然候选的构造器(当然是以标注了@Autowired的为准)
						 else if (candidate.getParameterCount() == 0) {
							// 这里注意:虽然把默认的构造函数记录下来了,但是并没有加进candidates里
							defaultConstructor = candidate;
						}
					}

					// 若能找到候选的构造器,这里注意,如果仅仅只有一个构造器的情况(没有标注@Autowired注解),这个亏胡原始股fakse,下面的elseif会处理的。。。。
					if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						// 这个是candidates里面有值了,并且还没有requiredConstructor (相当于标注了注解@Autowired,但是required=false)   的情况下,会吧默认的构造函数加进candidates
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
								candidates.add(defaultConstructor);
							}
							//如果没有默认的无参构造函数,且有@Autowired(required = false)的构造函数,则发出警告信
							else if (candidates.size() == 1 && logger.isWarnEnabled()) {
								logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
										"': single autowire-marked constructor flagged as optional - " +
										"this constructor is effectively required since there is no " +
										"default constructor to fall back to: " + candidates.get(0));
							}
						}
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}

					// 这个意思是:有且仅有一个构造器,并且该构造器的参数大于0个,那就是我们要找的构造器了
					// 这种情况,也是平时我们使用得比较多的情况
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
					}
					
					// 处理primaryConstructor以及nonSyntheticConstructors    兼容Kotlin一般都达不到
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null
							&& defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
					}
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					// 啥构造器都没找到,那就是空数组
					else {
						candidateConstructors = new Constructor<?>[0];
					}
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		// 若有多个构造函数,但是没有一个标记了@Autowired,此处不会报错,但是返回null,交给后面的策略处理
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}

可能有小伙伴会问:其实最终找到的构造器都是一个,这里为何返回一个数组呢?如果是这么认为,那你就还是没有太完全理解这里面的处理原理,比如下面情况:

代码语言:javascript
复制
@Service
public class HelloServiceImpl implements HelloService {

    private ApplicationContext applicationContext;
    private BeanFactory beanFactory;

    @Autowired(required = false)
    public HelloServiceImpl(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Autowired(required = false)
    public HelloServiceImpl(ApplicationContext applicationContext, BeanFactory beanFactory) {
        this.applicationContext = applicationContext;
        this.beanFactory = beanFactory;
    }
}

这里就返回的是2个构造器。这里最终会执行2个参数的构造器。这种情况:

代码语言:javascript
复制
    private ApplicationContext applicationContext;
    private BeanFactory beanFactory;

    HelloServiceImpl() {
        System.out.println("我是空构造~");
    }

    @Autowired(required = false)
    public HelloServiceImpl(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Autowired(required = false)
    public HelloServiceImpl(ApplicationContext applicationContext, BeanFactory beanFactory) {
        this.applicationContext = applicationContext;
        this.beanFactory = beanFactory;
    }

会返回3个构造器。最终执行的,还是参数最多的那个构造器。若返回多个构造器,Spring具体的执行策略,下面继续说:

Spring初始化Bean的执行策略(实例化Bean的过程)

主要处理代码如下:

代码语言:javascript
复制
		if (ctors != null ||
				// 或者标注了处理机制是构造器注入方式 AbstractBeanDefinition#setAutowireMode可以设置模式
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			
			// 构造器选择策略,注入逻辑
			return autowireConstructor(beanName, mbd, ctors, args);
		}

ConstructorResolver#autowireConstructor

这个方法作用是获取被包装后的bean,包装后的对象是BeanWrapper对象,这个对象的实现类是BeanWrapperImpl。其中包含被封装后待处理的bean,和设置bean属性的属性编辑器。

代码语言:javascript
复制
	protected BeanWrapper autowireConstructor(
			String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

		// 此处的this,就是DefaultListableBeanFactory嘛
		return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
	}


// ConstructorResolver#autowireConstructor
	public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) {

		//先实例化一个BeanWrapperImpl类对象
		BeanWrapperImpl bw = new BeanWrapperImpl();
		// initBeanWrapper做了一些事,比如注册解析器、value解析器等等  这是个比较大的概念,后面会有专题再说吧
		this.beanFactory.initBeanWrapper(bw);

		Constructor<?> constructorToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;

		 //如果构造参数不为空就直接使用这些参数即可
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		// 否则构造函数的入参,交给Spring处理。它会去容器里拿~~~~~
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {

				//获取已缓存解析的构造函数或工厂方法(resolvedConstructorOrFactoryMethod----用于缓存已解析的构造函数或工厂方法)
                constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
			
				////如果缓存不为空,并且构造参数已经解析缓存了,(constructorArgumentsResolved为包可见,用于表示构造参数状态是否已经解析)
				// 显然首次进来,都是为null并且没有被解析的
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			// 如果上面没有解析过,显然这里参数就是null了,argsToUse也就还为null Spring下面继续解析
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}
		//如果缓存的构造器不存在,就说明没有bean进行过解析,需要去关联对应的bean的构造器
		if (constructorToUse == null) {
			// Need to resolve the constructor.
			// 我们的传值chosenCtors 显然不为null,所以此值为true
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			int minNrOfArgs;
			//若传入的构造参数不为空,那最小参数长度一塔为准	
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				// 这里相当于要解析出构造函数的参数了
				//解析对应的构造参数然后添加到ConstructorArgumentValues中
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}

			// Take specified constructors, if any.
			//如果传入的构造器为空,则获取bean的Class对象,然后根据bean是不是public修饰的来按照不同的方式获取所有的构造器
			// 显然,我们这里(大都都会有构造器)
			// 但是此处我们发现,即使构造器不是public的,这里也能够遭到构造器来进行实例化
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					//getDeclaredConstructors返回所有的构造器(包括public和private修饰的),getConstructors返回public修饰的
					candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				} catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Resolution of declared constructors on bean Class [" + beanClass.getName() +
							"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
				}
			}
			// 这个构造器排序有点意思
			//按照访问方式和数量对构造器进行排序;public>protect>private,在同为public时构造器入参多的排在前面
			// 所以排在第一位的,是public的,参数最多的构造器
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;

			// 记录下,引起歧义的构造器们。就是记录下来,如果存在这种歧义,抛异常的时候用来告诉调用者
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;
			// 开始遍历排序后的构造器了==========================
			for (Constructor<?> candidate : candidates) {
				// 拿到构造器参数的类型们
				Class<?>[] paramTypes = candidate.getParameterTypes();

				// constructorToUse不为null(表示已经找到了合适构造器),但是呢,连参数个数的长度都对应不上,那就直接break,后面的构造器全都不用看了
				if (constructorToUse != null && argsToUse.length > paramTypes.length) {
					// Already found greedy constructor that can be satisfied ->
					// do not look any further, there are only less greedy constructors left.
					break;
				}
				// 如果参数个数比最小个数还小,那就继续下一个构造器吧。
				if (paramTypes.length < minNrOfArgs) {
					continue;
				}

				ArgumentsHolder argsHolder;
				if (resolvedValues != null) {
					try {
						
						//兼容JDK6提供的@ConstructorProperties这个注解,如果它标注了参数名,那就以它的名字为准
						//@ConstructorProperties的作用=======》构造函数上的注解,显示该构造函数的参数如何与构造对象的getter方法相对应
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);

						// 否则,就自己解析
						if (paramNames == null) {
							// 一般都是Bean工厂默认的DefaultParameterNameDiscoverer 解析出变量名
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								paramNames = pnd.getParameterNames(candidate);
							}
						}

						//根据获取到的参数名和已经查到的构造参数和构造参数类型来创建用户创建构造器用的构造参数数组
						//这个数组中包含了原始的参数列表和构造后的参数列表,用来对比用
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring);
					} catch (UnsatisfiedDependencyException ex) {
						if (this.beanFactory.logger.isTraceEnabled()) {
							this.beanFactory.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);
				}
				//lenientConstructorResolution的值ture与false有什么区别:
				//这个属性默认值是true,在大部分情况下都是使用[宽松模式],即使多个构造函数的参数数量相同、类型存在父子类、接口实现类关系也能正常创建bean。
				// false表示严格模式。与上面相反
				// typeDiffWeight:返回不同的个数的权重(权重概念?)
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				// 根据权重,选择一个最为合适的构造器
				if (typeDiffWeight < minTypeDiffWeight) {
					// 大都进这里来,然后是木有ambiguousConstructors 的
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}

			// 如果此时还没发现可用的构造器,那这里就开始处理异常吧~
			if (constructorToUse == null) {
				if (causes != null) {
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Could not resolve matching constructor " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
			} else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous constructor matches found in bean '" + beanName + "' " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousConstructors);
			}

			if (explicitArgs == null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}


		//下面步骤都是通用的,用上面得到的构造器(无论是从bean对象中获取的还是spring自己构建的)
		// 和参数来反射创建bean实例,并放到BeanWrapperImpl对象中然后返回
		try {
			// 拿到生成Bean实例化策略,默认值为CglibSubclassingInstantiationStrategy  用CGLIB生成子类的方式
			final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();
			Object beanInstance;

			if (System.getSecurityManager() != null) {
				final Constructor<?> ctorToUse = constructorToUse;
				final Object[] argumentsToUse = argsToUse;
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),
						beanFactory.getAccessControlContext());
			}
			else {
				// 主要就是调用了策略器的instantiate,对Bean进行了最终的实例化
				// 此方法为重载方法,此处因为不需要代理,所以执行的直接是SimpleInstantiationStrategy#instantiate
				// 到此处,有一个HelloServiceImpl正式创建   然后继续到doCreateBean方法去吧
				beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
			}

			bw.setBeanInstance(beanInstance);
			return bw;
		} catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via constructor failed", ex);
		}
	}
populateBean和initializeBean

具体他俩做了什么,参考:【小家Spring】AbstractAutowireCapableBeanFactory#populateBean实现Bean的依赖注入(属性赋值)和initializeBean对Bean的初始化

总结

getBean()方法是Spring IOC容器实例化、初始化Bean的核心方法,里面的逻辑也异常的复杂。

通过阅读源码,感受最深的是:

一个优秀的框架,决不仅仅是说可以通过反射能帮助创建Bean就行了,而是像Spring这样能够考虑到各式各样的情况,有非常好的容错性、有很好的异常处理以及提示调用者报错原因。当然也有一一系列的设计原则的体现:单一职责原则、面向对象的设计原则、对扩展开放对修改关闭的原则(BeanPostProcessor是个非常好的钩子,允许我们参与进Bean的声明周期中来)

阅读优秀的源码,能够在我们更深的理解到:优秀只所以优秀,是因为真的很优秀!!!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年03月10日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • getBean方法概述
  • AbstractBeanFactory#doGetBean
  • BeanPostProcessor和InstantiationAwareBeanPostProcessor和SmartInstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor
    • 子接口:SmartInstantiationAwareBeanPostProcessor
      • 子类MergedBeanDefinitionPostProcessor
        • 讲解之前,贤了解下BeanWrapper吧:
          • doCreateBean源码解析
            • Spring初始化Bean的执行策略(实例化Bean的过程)
              • populateBean和initializeBean
              • 总结
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档