深入理解-Spring-之源码剖析IOC(二)

简介:

5. 如何创建Bean实例并构建Bean的依赖关系网

我们刚刚创建了Bean工厂,并创建 BeanDefinitions 放进Map里,以beanName为key。那么我们现在有了Bean定义,但还没有实例,也没有构建Bean与Bean之间的依赖关系。

我们知道,构建依赖关系是 IOC 的一个重要的任务,我们怎么能放过。那么是在哪里做的呢?在 finishBeanFactoryInitialization(beanFactory) 方法中。该方法中重要的一步是 : beanFactory.preInstantiateSingletons(),我们有必要看看该方法实现:

 
@Override
public void preInstantiateSingletons() throws BeansException {
if ( this .logger.isDebugEnabled()) {
this .logger.debug( "Pre-instantiating singletons in " + this );
}

// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>( this .beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); // 注意:FactoryBean
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
((SmartFactoryBean<?>) factory).isEagerInit(),
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName); // 创建bean
}
}
}

// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null ) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null ;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}

该方法首先循环所有的BeanNames,并且调用getBean方法,该方法实际上就是创建bean并递归构建依赖关系。该方法会调用 doGetBean(name, null, null, false),我们进入该方法查看,该方法很长,楼主挑选重要代码:

 
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);
getBean(dep); // 递归
}} // Create bean instance.if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}

可以看到,该方法首先会获取依赖关系,拿着依赖的BeanName 递归调用 getBean方法,直到调用 getSingleton 方法返回依赖bean,而 getSingleton 方法的参数是 createBean 返回的实例,该方法内部调用 AbstractAutowireCapableBeanFactory.doCreateBean 方法:

 
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);
}
if (instanceWrapper == null ) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed" , ex);
}
mbd.postProcessed = true ;
}
}

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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" );
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed" , ex);
}
}

if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false );
if (earlySingletonReference != null ) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (! this .allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String [] dependentBeans = getDependentBeans(beanName);
Set< String > actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for ( String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example." );
}
}
}
}

// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature" , ex);
}

return exposedObject;
}

该方法很长,我们重点关注以下2行代码:

instanceWrapper = createBeanInstance(beanName, mbd, args) 创建实例。

populateBean(beanName, mbd, instanceWrapper) , 该方法用于填充Bean,该

  1. 方法可以就是说就是发生依赖注入的地方。

我们看看 createBeanInstance 方法:

 
protected BeanWrapper createBeanInstance( String beanName, RootBeanDefinition mbd, @Nullable Object [] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);

if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null ) {
return obtainFromSupplier(instanceSupplier, beanName);
}

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

// Shortcut when re-creating the same bean...
boolean resolved = false ;
boolean autowireNecessary = false ;
if (args == null ) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null ) {
resolved = true ;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null , null );
}
else {
return instantiateBean(beanName, mbd);
}
}

// Need to determine the constructor...
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);
}

该方法的doc注释是这样介绍的:为指定的bean创建一个新的实例,使用适当的实例化策略:工厂方法、构造函数自动装配或简单实例化。

我们看,该方法首先创建Class 对象,然后获取构造器对象,最后调用 instantiateBean(beanName, mbd) 方法,我们看看该方法实现:

 
protected BeanWrapper instantiateBean( final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null ) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent ),
getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent );
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed" , ex);
}
}

该方法核心逻辑是 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent),携带BeanName ,RootBeanDefinition ,发挥的策略对象是 SimpleInstantiationStrategy,该方法内部调用静态方法 BeanUtils.instantiateClass(constructorToUse), 组后调用 Constructor 的 newInstance 方法, 也就是最终使用反射创建了该实例:

 
public static <T> T instantiateClass (Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null" );
try {
ReflectionUtils.makeAccessible(ctor);
return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?" , ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?" , ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor" , ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception" , ex.getTargetException());
}
}

该方法会判断是否是 Kotlin 类型。如果不是,则调用构造器的实例方法。

到这里,我们的实例已经创建。但是我们的实例的依赖还没有设置,刚刚我们在 doCreateBean方法说关心以下2行代码:

instanceWrapper = createBeanInstance(beanName, mbd, args) 创建实例。

populateBean(beanName, mbd, instanceWrapper) , 该方法用于填充Bean,该方法可以就是说就是发生依赖注入的地方。

我们已经解析了第一个,现在看第二个方法:

 
protected void populateBean( String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null ) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance" );
}
else {
// Skip property population phase for null instance.
return ;
}
}

// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true ;

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 ;
}
}
}
}

if (!continueWithPropertyPopulation) {
return ;
}

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null );

if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}

// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}

pvs = newPvs;
}

boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null ) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null ) {
return ;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}

if (pvs != null ) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}

该方法核心逻辑是

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null),

即获取该bean的所有属性,也就是我们配置property元素。最后执行 applyPropertyValues(beanName, mbd, bw, pvs) 方法。

注意,现在的PropertyValues 都是字符串,没有值的,这个方法的作用就是获取值,关键代码:

Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue)

该方法会获取 pvName 所对应的容器value,该方法内部会调用 BeanWrapperImpl.resolveReference(argName, ref) 方法,我们看看该方法:

 
@Nullable
private Object resolveReference( Object argName, RuntimeBeanReference ref) {
try {
Object bean;
String refName = ref.getBeanName();
refName = String .valueOf(doEvaluate(refName));
if (ref.isToParent()) {
if ( this .beanFactory.getParentBeanFactory() == null ) {
throw new BeanCreationException(
this .beanDefinition.getResourceDescription(), this .beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available" );
}
bean = this .beanFactory.getParentBeanFactory().getBean(refName);
}
else {
bean = this .beanFactory.getBean(refName);
this .beanFactory.registerDependentBean(refName, this .beanName);
}
if (bean instanceof NullBean) {
bean = null ;
}
return bean;
}
catch (BeansException ex) {
throw new BeanCreationException(
this .beanDefinition.getResourceDescription(), this .beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}

其中有一行熟悉的代码:bean = this.beanFactory.getBean(refName),对,这里就是发生递归的地方。该方法会拿着属性名称从容器中获取实例。

我们回到 applyPropertyValues 方法。此时deepCopy 集合已经有值了,不再仅仅是字符串了。

然后调用 setPropertyValues(new MutablePropertyValues(deepCopy)) 方法, 该方法会调用 AbstractPropertyAccessor.setPropertyValues 方法完成注入,而该方法会循环元素列表, 循环中调用 setPropertyValue(PropertyValue pv) 方法, 该方法最后会调用 nestedPa.setPropertyValue(tokens, pv) 方法, 该方法又会调用 processLocalProperty(tokens, pv) 方法,该方法最后又会调用 ph.setValue(valueToApply) 方法,也就是BeanWrapperImpl.setValue() 方法,终于,我们要看到反射了,看到反射说明到了尽头。

 
@Override
public void setValue(final @Nullable Object value) throws Exception {
final Method writeMethod = ( this .pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this .pd).getWriteMethodForActualAccess() :
this .pd.getWriteMethod());
if (System.getSecurityManager() != null ) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(writeMethod);
return null ;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
writeMethod.invoke(getWrappedInstance(), value), acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
ReflectionUtils.makeAccessible(writeMethod);
writeMethod.invoke(getWrappedInstance(), value);
}
}

该方法是最后一步,我们看到该方法会找的set方法,然后调用 Method 的 invoke 方法,完成属性注入。

6. 总结

我们从源码层面剖析 IOC 的初始化过程,也了解了 IOC 的底层原理实现, 我们总结一下:

Spring 的 Bean 其实就是 BeanDefinition, 在 Bean 的创建和依赖注入的过程中, 需要根据 BeanDefinition 的信息来递归的完成依赖注入。

从我们分析的代码可以看到,这些递归都是以 getBean() 为入口的, 一个递归是在上下文体系中查找需要的 Bean 和创建 Bean 的递归调用, 另一个 Bean 实在依赖注入时,通过递归调用容器的 getBean 方法, 得到当前的依赖 Bean, 同时也触发对依赖 Bean 的创建和注入。

在对 Bean 的属性尽心依赖注入时, 解析的过程也是一个递归的过程, 这样, 根据依赖关系, 一层一层的完成 Bean 的创建和注入, 知道最后完成当前 Bean 的创建, 有了这个顶层 Bean 的创建和对他的属性依赖注入的完成, 意味着当前 Bean 相关的整个依赖链的注入也完成了.

总结一下 IOC 的初始化过程吧:

  1. 资源(Resource)定位;

  2. BeanDefinition 的载入和 BeanFactory 的构造.

  3. 想 IOC 容器(BeanFactory)注册 BeanDefinition.

  4. 根据 lazy-init 属性初始化 Bean 实例和依赖注入.

现在回过头看看, 我们已经了解了 Spring IOC 的设计, 那么我们自己可以实现一个简单的 IOC 吗? 楼主想试试,并且楼主已经写好了,下篇和大家一起实现一个简单的 IOC。


原文发布时间为:2018-09-7

本文作者:莫那鲁道

本文来自云栖社区合作伙伴“Java架构沉思录”,了解相关信息可以关注“Java架构沉思录”。

相关文章
|
1月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
2月前
|
监控 数据可视化 关系型数据库
微服务架构+Java+Spring Cloud +UniApp +MySql智慧工地系统源码
项目管理:项目名称、施工单位名称、项目地址、项目地址、总造价、总面积、施工准可证、开工日期、计划竣工日期、项目状态等。
304 6
|
2月前
|
Java 关系型数据库 数据库连接
Spring源码解析--深入Spring事务原理
本文将带领大家领略Spring事务的风采,Spring事务是我们在日常开发中经常会遇到的,也是各种大小面试中的高频题,希望通过本文,能让大家对Spring事务有个深入的了解,无论开发还是面试,都不会让Spring事务成为拦路虎。
33 1
|
1月前
|
Java 测试技术 数据库连接
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
|
1月前
|
Java 数据库连接 API
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
46 0
|
13天前
|
XML Java 数据格式
Spring(一)IOC小案例
Spring(一)IOC小案例
|
27天前
|
Java Spring
使用spring实现邮件的发送(含测试,源码,注释)
使用spring实现邮件的发送(含测试,源码,注释)
7 0
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (下)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)
|
1月前
|
Java Spring 容器
【Spring源码】单例创建期间进行同步可能会导致死锁?
通过这个标题我们就可以思考本次的阅读线索了,看起来可以学到不少东西。1. 旧代码的死锁是怎么产生的。2. 贡献者通过改变什么来解决本次PR的问题呢?而阅读线索2的答案也显而易见,就是上文提到的通过后台线程来创建Micrometer单例...
39 3