第二章 Spring bean实例化、IOC、循环依赖笔记

一、Bean的实例化过程

流程图地址:https://www.processon.com/view/link/5df87156e4b0cfc88c3c18c5

org.springframework.context.support.AbstractApplicationContext#refresh方法中

/*
* 这个方法是spring中最重要的方法,没有之一所以这个方法一定要理解要具体看
* 1、bean实例化过程
* 2、ioc
* 3、注解支持
* 4、BeanPostProcessor的执行
* 5、Aop的入口
*/
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

1、BeanDefinitionRegistryPostProcessor接口

Refresh().invokeBeanFactoryPostProcessors这个方法里面。

BeanDefinitionRegistryPostProcessor这个接口的调用分为三部:

1)调用实现了PriorityOrdered排序接口

2)调用实现了Ordered排序接口

3)没有实现接口的调用

这个接口的理解:获取BeanDefinitionRegistry对象,获取到这个对象就可以获取这个对象中注册的所有BeanDefinition对象,所以我们知道了,我们拥有这个对象就可以完成里面所有BeanDefinition对象的修改我新增操作。

@Component
public class BeanDefinitionTest implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        genericBeanDefinition.setBeanClass(BeanClass.class);
        MutablePropertyValues propertyValues = genericBeanDefinition.getPropertyValues();
        propertyValues.addPropertyValue("username","Hnakin")
        registry.registerBeanDefinition("beanClass",genericBeanDefinition);
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry);
        //TODO 将自定义的注解@MyService添加到ClassPathBeanDefinitionScanner
        // private final List<TypeFilter> includeFilters = new LinkedList<>();
        scanner.addIncludeFilter(new AnnotationTypeFilter(MyService.class));
        scanner.scan("com.chj");
    }

2、BeanPostProcessor的注册

Refresh().registerBeanPostProcessors这个方法里面。

org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors

// Register bean processors that intercept bean creation.

registerBeanPostProcessors(beanFactory);

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

拿到BeanFactory中所有注册的BeanDefinition对象的名称beanName。

for (String ppName : postProcessorNames) {
   if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      priorityOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
      orderedPostProcessorNames.add(ppName);
   }else {
      nonOrderedPostProcessorNames.add(ppName);
   }
}

然后判断是否实现了PriorityOrdered排序接口,Ordered排序接口,getBean是将该ppName对应的BeanDefinition对象实例化。

registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

把对应的BeanPostProcessor对象注册到BeanFactory中,BeanFactory中有一个list容器接收。

3、getSingleton方法

代码位置: AbstractBeanFactory.doGetBean方法中

// Create bean instance.
if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, () -> {
      try {
         return createBean(beanName, mbd, args);
      }
      catch (BeansException ex) {
         destroySingleton(beanName);
         throw ex;
      }
   });
   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

方法里面核心要点:

beforeSingletonCreation(beanName);

protected void beforeSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
   }
}

把beanName添加到singletonsCurrentlyInCreation Set容器中,在这个集合里面的bean都是正在实例化的bean,就是实例化还没做完的BeanName。

try {
   singletonObject = singletonFactory.getObject();
   newSingleton = true;
}

调到getObject方法,完成bean的实例化。接下来

finally {
   if (recordSuppressedExceptions) {
      this.suppressedExceptions = null;
   }
   afterSingletonCreation(beanName);
}
if (newSingleton) {
   addSingleton(beanName, singletonObject);
}

getObject 调用完后,就代表着 Bean 实例化已经完成了,这时候就需要

1)singletonsCurrentlyInCreation 把 beanName 从这个集合中删除

2)addSingleton,把 bean 缓存到一级缓存中

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }

4、createBean方法,具体实例化过程

代码位置:AbstractBeanFactory.doGetBean方法中

注意:默认初始化bean的条件是非抽象类,单例且非懒加载。

@Override
public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }
   //xml解析时,讲过,把所有beanName都缓存到beanDefinitionNames了
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
      //把父BeanDefinition里面的属性拿到子BeanDefinition中
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //如果不是抽象的,单例的,非懒加载的就实例化
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         //判断bean是否实现了FactoryBean接口,这里可以不看
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               final FactoryBean<?> factory = (FactoryBean<?>) bean;
               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);
         }
      }
   }
   // 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();
         }
      }
   }
}

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

//如果是scope 是Prototype的,校验是否有出现循环依赖,如果有则直接报错
if (isPrototypeCurrentlyInCreation(beanName)) {
   throw new BeanCurrentlyInCreationException(beanName);
}

//着重看,大部分是单例的情况
// Create bean instance.
if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, () -> {
      try {
         return createBean(beanName, mbd, args);
      }catch (BeansException ex) {
         destroySingleton(beanName);
         throw ex;
      }
   });
   //方法是FactoryBean接口的调用入口
   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

4.1、进入方法createBean(beanName, mbd, args);

这个方法是bean实例化核心方法:

org.springframework.beans.factory.support.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) {
      //创建实例,,重点看,重要程度:5
      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 {
            //CommonAnnotationBeanPostProcessor  支持了@PostConstruct,@PreDestroy,@Resource注解
            //AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
            //BeanPostProcessor接口的典型运用,这里要理解这个接口
            //对类中注解的装配过程
            //重要程度5,必须看
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         mbd.postProcessed = true;
      }
   }
   //是否   单例bean提前暴露
   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");
      }
      //这里着重理解,对理解循环依赖帮助非常大,重要程度 5   添加三级缓存
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }
   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      //ioc di,依赖注入的核心方法,该方法必须看,重要程度:5
      populateBean(beanName, mbd, instanceWrapper);
      //bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5
      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) {
......
     }
   }
   // Register bean as disposable.
   try {
      //注册bean销毁时的类DisposableBeanAdapter
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }
   return exposedObject;
}

实例化方法,把bean实例化,并且包装成BeanWrapper。

4.2、点进instantiateUsingFactoryMethod这个方法里面

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

这个方法是反射调用类中的factoryMethod方法。这要知道@Bean方法的原理,实际上spring会扫描有@bean注解的方法,然后把方法名称设置到BeanDefinition的factoryMethod属性中,接下来就会调到上面截图中的方法实现@Bean方法的调用。该方法里面的参数解析过程不需要了解。

1)有参构造函数的时候

// 寻找当前bean中有@Autowired注解的构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
      mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
   return autowireConstructor(beanName, mbd, ctors, args);
}

determineConstructorsFromBeanPostProcessors这个方法是BeanPostProcessor接口类的首次应用,最终会掉到AutowiredAnnotationBeanPostProcessor类的方法,在方法中会扫描有注解的构造函数然后完成装配过程。

2)无参构造函数的实例化

//无参构造函数的实例化,大部分的实例是采用的无参构造函数的方式实例化
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);

这就是简单的反射实例化大部分类的实例化都会走这个逻辑

4.3、类中注解的收集@Autowired或者@Resource

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

实例化完成后接下来就需要对类中的属性进行依赖注入操作,但是类里面属性和方法的依赖注入往往用@Autowired或者@Resource 注解,那么这些注解的依赖注入是如何完成的呢?

注解的收集:

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
   if (!mbd.postProcessed) {
      try {
         //CommonAnnotationBeanPostProcessor  支持了@PostConstruct,@PreDestroy,@Resource注解
         //AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
         //BeanPostProcessor接口的典型运用,这里要理解这个接口
         //对类中注解的装配过程
         //重要程度5,必须看
         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      } catch (Throwable ex) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "Post-processing of merged bean definition failed", ex);
      }
      mbd.postProcessed = true;
   }
}

也是通过 BeanPostProcessor 接口类型实例来挨个处理的。

4.3.1、首先是CommonAnnotationBeanPostProcessor类,这个类完成了@Resource 注解的属性或者方法的收集,这个类还对@PostConstruct@PreDestory支持

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

 

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

/*
* 1、扫描类里面的属性或者方法
* 2、判断属性或者方法上面是否有@PostConstruct @PreDestroy @Resource注解
* 3、如果有注解的属性或者方法,包装成一个类
* */
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
   //扫描@PostConstruct @PreDestroy
   super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
   //扫描@Resource,扫描属性和方法上面是否有@Resource注解,如果有则收集起来封装成对象
   InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
   metadata.checkConfigMembers(beanDefinition);
}

CommonAnnotationBeanPostProcessor的构造方法:

public CommonAnnotationBeanPostProcessor() {
   setOrder(Ordered.LOWEST_PRECEDENCE - 3);
   setInitAnnotationType(PostConstruct.class);
   setDestroyAnnotationType(PreDestroy.class);
   ignoreResourceType("javax.xml.ws.WebServiceContext");
}

4.3.2、收集过程:

1)看缓存里面有没有InjectionMetadata对象

private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
   String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
   // Quick check on the concurrent map first, with minimal locking.
   InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
   if (InjectionMetadata.needsRefresh(metadata, clazz)) {
      synchronized (this.injectionMetadataCache) {
         metadata = this.injectionMetadataCache.get(cacheKey);
         if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            if (metadata != null) {
               metadata.clear(pvs);
            }
            //主要看这个方法
            metadata = buildResourceMetadata(clazz);
            this.injectionMetadataCache.put(cacheKey, metadata);
         }
      }
   }
   return metadata;
}

2)从类中获取所有Field对象,循环field对象,判断field有没有@Resource注解,如果有注解封装成 ResourceElement对象。

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildResourceMetadata

ReflectionUtils.doWithLocalFields(targetClass, field -> {

else if (field.isAnnotationPresent(Resource.class)) {
   if (Modifier.isStatic(field.getModifiers())) {
      throw new IllegalStateException("@Resource annotation is not supported on static fields");
   }
   if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
      currElements.add(new ResourceElement(field, field, null));
   }
}

3)从类中获取所有Method对象,循环Method对象,判断Method有没有@Resource注解,如果有注解封装成ResourceElement对象。

ReflectionUtils.doWithLocalMethods(targetClass, method -> {

else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
   if (Modifier.isStatic(method.getModifiers())) {
      throw new IllegalStateException("@Resource annotation is not supported on static methods");
   }
   Class<?>[] paramTypes = method.getParameterTypes();
   if (paramTypes.length != 1) {
      throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
   }
   if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
      PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
      currElements.add(new ResourceElement(method, bridgedMethod, pd));
   }
}

4)最终把两个field和Method封装的对象集合封装到InjectionMetadata对象中。

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
   List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();

elements.addAll(0, currElements);

return new InjectionMetadata(clazz, elements);

4.3.3、然后是AutowiredAnnotationBeanPostProcessor类,对@Autowired注解的属性和方法的收集。

收集过程基本上跟@Resource 注解的收集差不多,这里就不赘述了。

5、注解@Resource与@Autowired的区别

@Resource注解

@Resource有两个常用属性name、type,所以分4种情况

指定name和type:通过name找到唯一的bean,找不到抛出异常;如果type和字段类型不一致,也会抛出异常

指定name:通过name找到唯一的bean,找不到抛出异常

指定type:通过tpye找到唯一的bean,如果不唯一,则抛出异常:NoUniqueBeanDefinitionException

都不指定:通过字段名作为key去查找,找到则赋值;找不到则再通过字段类型去查找,如果不唯一,则抛出异常:NoUniqueBeanDefinitionException

@Autowired注解

@Autowired只有一个属性required,默认值为true,为true时,找不到就抛异常,为false时,找不到就赋值为null。

@Autowired按类型查找,如果该类型的bean不唯一,则抛出异常;可通过组合注解解决@Autowired()@Qualifier("baseDao")。

相同点:

Spring都支持

都可以作用在字段和setter方法上

不同点:

  • Resource是JDK提供的,而Autowired是Spring提供的;
  • Resource不允许找不到bean的情况,而Autowired允许(@Autowired(required = false));
  • 指定name的方式不一样,@Resource(name = "baseDao"),@Autowired()@Qualifier("baseDao");
  • Resource默认通过name查找,而Autowired默认通过type查找。

二、IOC\DI依赖注入与循环依赖分析

1、IOC\DI依赖注入

经过AbstractAutowireCapableBeanFactory#doCreateBean方法的下面两个方法,完成了spring工厂对bean的创建,和类属性注解的扫描装配过程。

if (instanceWrapper == null) {
   //创建实例,,重点看,重要程度:5
   instanceWrapper = createBeanInstance(beanName, mbd, args);
}

try {
   //CommonAnnotationBeanPostProcessor  支持了@PostConstruct,@PreDestroy,@Resource注解
   //AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
   //BeanPostProcessor接口的典型运用,这里要理解这个接口
   //对类中注解的装配过程
   //重要程度5,必须看
   applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}

然后将首次创建的单实例bean提前暴露,放到三级缓冲中(循环依赖使用)

1.1、是否单例bean提前暴露

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");
   }
   //这里着重理解,对理解循环依赖帮助非常大,重要程度 5   添加三级缓存
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

三级缓存对象工厂ObjectFactory.getObject()调用到这个方法

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
   }
   return exposedObject;
}

SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference

default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
   return bean;
}

1.2、对应的方法populateBean:

try {
   //ioc di,依赖注入的核心方法,该方法必须看,重要程度:5
   populateBean(beanName, mbd, instanceWrapper);
   //bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5
   exposedObject = initializeBean(beanName, exposedObject, mbd);
}

看到这个if代码块

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

//重点看这个if代码块,重要程度 5
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);
            }
            //老版本用这个完成依赖注入过程,@Autowired的支持
            pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
               return;
            }
         }
         pvs = pvsToUse;
      }
   }
}

这里又是一个BeanPostProcessor类型接口的运用,前面我们讲到了@Resource@Autowired注解的收集,那么这个方法就是根据收集到的注解进行反射调用。

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
   InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
   try {
      metadata.inject(bean, beanName, 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()) {
      for (InjectedElement element : elementsToIterate) {
         if (logger.isTraceEnabled()) {
            logger.trace("Processing injected element of bean '" + beanName + "': " + element);
         }
         element.inject(target, beanName, pvs);
      }
   }
}

循环收集到的metaData中的list对象,然后挨个调用里面的InjectedElement的inject方法完成依赖注入。

try {
   Method method = (Method) this.member;
   ReflectionUtils.makeAccessible(method);
   method.invoke(target, getResourceToInject(target, requestingBeanName));
}

其中value值的获取,如果依赖的属性是一个引用类型必定会触发该属性的BeanFactory.getBean操作,从而从spring容器中获取到对应的实例。方法的依赖注入类似这里就不再赘述。

上述是对注解@Resource和@Autowired的依赖注入的实现逻辑,xml配置的依赖注入,比如在bean标签中配置了: <property name="age" value="18"/>

标签的依赖注入是这个逻辑:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

//这个方法很鸡肋了,建议不看,是老版本用<property name="username" value="hankin"/>
//标签做依赖注入的代码实现,复杂且无用
if (pvs != null) {
   applyPropertyValues(beanName, mbd, bw, pvs);
}

这块逻辑是专门做xml配置依赖注入的,基本上现在基于xml配置的依赖很少使用,这里就不讲这块逻辑,没多大用。

2、单实例bean的循环依赖分析

假设业务bean CircularRefA里面,属性注入了CircularRefB,而且CircularRefB的属性里面也注入了CircularRefA,如此就形成了循环依赖的问题。

@Service
public class CircularRefA {
    @Value("123")
    private String username;
    @Autowired
    private CircularRefB circularRefB;
}

@Service
public class CircularRefB {
    @Value("xxxk")
    private String username;
    @Autowired
    private CircularRefA circularRefA;
}

2.1、流程图如下

流程如地址:https://www.processon.com/view/link/5df9ce52e4b0c4255ea1a84f

 

2.2、从缓冲中获取bean实例的源码

1)根据beanName从缓存中拿实例,先从一级缓存拿;

2)如果一级缓存没有,从二级缓存中拿;

3)如果还拿不到,并且允许bean提前暴露,从三级缓存中拿到对象工厂

4)如果三级缓存中存在,则从工厂中拿到对象,然后升级到二级缓存,删除三级缓存

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
   //一级缓存
   private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  //级缓存
   private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  //级缓存
   private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   //根据beanName从缓存中拿实例
   //先从一级缓存拿
   Object singletonObject = this.singletonObjects.get(beanName);
   //如果bean还正在创建,还没创建完成,其实就是堆内存有了,属性还没有DI依赖注入
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         //从二级缓存中拿
         singletonObject = this.earlySingletonObjects.get(beanName);
         //如果还拿不到,并且允许bean提前暴露
         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;
}

2.3、如果缓存中没有,触发getBean方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

1)CircularRefA首先执行doCreateBean方法,继续创建bean,并扫描属性注解。

//创建实例,,重点看,重要程度:5
instanceWrapper = createBeanInstance(beanName, mbd, args);

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

注意:此时CircularRefA还没有完全完成bean的实例化加属性赋值,但是该对象已经实例化,并且放到了三级缓存。

2)CircularRefA执行是否单例bean提前暴露,然后放入三级缓冲singletonFactories中

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");
   }
   //这里着重理解,对理解循环依赖帮助非常大,重要程度 5   添加三级缓存
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory, "Singleton factory must not be null");
   synchronized (this.singletonObjects) {
      if (!this.singletonObjects.containsKey(beanName)) {
         this.singletonFactories.put(beanName, singletonFactory);
         this.earlySingletonObjects.remove(beanName);
         this.registeredSingletons.add(beanName);
      }
   }
}

3)CircularRefA最后调用bean的属性赋值方法populateBean()

//ioc di,依赖注入的核心方法,该方法必须看,重要程度:5

populateBean(beanName, mbd, instanceWrapper);

2.4、执行@Autowired private CircularRefB circularRefB;

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//依赖注入过程,@Autowired的支持
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);

此时CircularRefA还没有完全完成bean的实例化加属性赋值,但是该对象已经实例化,并且放到了三级缓存,所以这个时候在完成属性CircularRefB的赋值的时候,又触发了对象CircularRefB的实例化操作,在完成CircularRefB对象的属性赋值的时候,可以获取到CircularRefA对象的实例,所以CircularRefB对象完成属性赋值,最后因为CircularRefB已经完成了实例化,所以CircularRefA对象可以完成最后的属性赋值。

2.5、实例化CircularRefB的过程中,又会引入CircularRefA

此时流程又回到到了开始阶段doGetBean方法,不过这个时候因为CircularRefA已经实例化,所以代码流程进入缓存singletonFactories中获取逻辑部分;获取到对象实例以后升级到二级缓存,然后删除三级缓存(注意三级缓存的生命周期只存在于对象创建的过程中,有点完成属性赋值就会删除)。

//如果还拿不到,并且允许bean提前暴露
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);
   }
}

3、bean实例化后的操作

3.1、代码走到这里initializeBean方法:

try {
   //ioc di,依赖注入的核心方法,该方法必须看,重要程度:5
   populateBean(beanName, mbd, instanceWrapper);
   //bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5
   exposedObject = initializeBean(beanName, exposedObject, mbd);
}

AbstractAutowireCapableBeanFactory#initializeBean(Object, RootBeanDefinition)

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 {
      //调用Aware方法
      invokeAwareMethods(beanName, bean);
   }
   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      //对类中某些特殊方法的调用,比如@PostConstruct,Aware接口,非常重要 重要程度 :5
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }
   try {
      //InitializingBean接口,afterPropertiesSet,init-method属性调用,非常重要,重要程度:5
      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()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }
   return wrappedBean;
}

3.2、首先是对某些Aware接口的调用

private void invokeAwareMethods(final String beanName, final Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware) bean).setBeanName(beanName);
      }
      if (bean instanceof BeanClassLoaderAware) {
         ClassLoader bcl = getBeanClassLoader();
         if (bcl != null) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
         }
      }
      if (bean instanceof BeanFactoryAware) {
         ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
   }
}

3.3、然后@PostConstruct注解方法的调用

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {
   Object result = existingBean;
   /*
   * 着重看几个
   * 1、ApplicationContextAwareProcessor  对某个Aware接口方法的调用
   * 2、InitDestroyAnnotationBeanPostProcessor  @PostConstruct注解方法的调用
   * 3、ImportAwareBeanPostProcessor  对ImportAware类型实例setImportMetadata调用
   * 这个对理解springboot有很大帮助。 这里暂时不需要深入看
   * */
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessBeforeInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}

这里又是一个BeanPostProcessor接口的运用,前面讲过,有@PostConstruct注解的方法会收集到一个metaData对象中,现在就是通过 BeanPostProcessor 接口调到CommonAnnotationBeanPostProcessor类,然后在类中拿到metaData对象,根据对象里面的容器来反射调用有注解的方法。

3.4、InitializingBean接口和init-method属性调用

//bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5

exposedObject = initializeBean(beanName, exposedObject, mbd);

//InitializingBean接口,afterPropertiesSet,init-method属性调用,非常重要,重要程度:5
invokeInitMethods(beanName, wrappedBean, mbd);

实现了InitializingBean接口的类就必然会调用到afterPropertiesSet

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
      throws Throwable {
   boolean isInitializingBean = (bean instanceof InitializingBean);
   if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
      if (logger.isTraceEnabled()) {
         logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
      }
      if (System.getSecurityManager() != null) {
         try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
               ((InitializingBean) bean).afterPropertiesSet();
               return null;
            }, getAccessControlContext());
         } catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      }else {
         ((InitializingBean) bean).afterPropertiesSet();
      }
   }

Init-method属性调用是在afterPropertiesSet之后
   if (mbd != null && bean.getClass() != NullBean.class) {
      String initMethodName = mbd.getInitMethodName();
      if (StringUtils.hasLength(initMethodName) &&
            !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
         invokeCustomInitMethod(beanName, bean, mbd);
      }
   }
}

在这个方法里面还有一个重要的逻辑:

if (mbd == null || !mbd.isSynthetic()) {
   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

也是一个BeanPostProcessor接口的运用,在这里会返回bean的代理实例,这个就是AOP的入口。

4、BeanPostProcessor 接口理解

BeanPostProcessor 接口类型实例是针对某种特定功能的埋点,在这个点会根据接口类型

来过滤掉不关注这个点的其他类,只有真正关注的类才会在这个点进行相应的功能实现。

4.1、获取有@Autowired注解的构造函数埋点

过滤的接口类型是:SmartInstantiationAwareBeanPostProcessor

调用的方法是:determineCandidateConstructors

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

if (instanceWrapper == null) {
   //创建实例,,重点看,重要程度:5
   instanceWrapper = createBeanInstance(beanName, mbd, args);
}

// Candidate constructors for autowiring?
//寻找当前正在实例化的bean中有@Autowired注解的构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
      mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
   //如果ctors不为空,就说明构造函数上有@Autowired注解
   return autowireConstructor(beanName, mbd, ctors, args);
}

4.2、收集@Resource@Autowired@Value@PostConstruct@PreDestroy注解的方法和属性埋点

过滤的接口类型是:MergedBeanDefinitionPostProcessor

调用的方法是:postProcessMergedBeanDefinition

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
   if (!mbd.postProcessed) {
      try {
         //CommonAnnotationBeanPostProcessor  支持了@PostConstruct,@PreDestroy,@Resource注解
         //AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
         //BeanPostProcessor接口的典型运用,这里要理解这个接口
         //对类中注解的装配过程
         //重要程度5,必须看
         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      } catch (Throwable ex) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "Post-processing of merged bean definition failed", ex);
      }
      mbd.postProcessed = true;
   }
}

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

4.3、循环依赖解决中 bean 的提前暴露埋点

过滤的接口类型是:SmartInstantiationAwareBeanPostProcessor

调用的方法是:getEarlyBeanReference

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//是否   单例bean提前暴露
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");
   }
   //这里着重理解,对理解循环依赖帮助非常大,重要程度 5   添加三级缓存
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

4.4、阻止依赖注入埋点

过滤的接口类型是:InstantiationAwareBeanPostProcessor

调用的方法是:postProcessAfterInstantiation

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

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

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

4.5、IOC/DI 依赖注入埋点

过滤的接口类型是:InstantiationAwareBeanPostProcessor

调用的方法是:postProcessProperties

//重点看这个if代码块,重要程度 5
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);
            }
            //老版本用这个完成依赖注入过程,@Autowired的支持
            pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
               return;
            }
         }
         pvs = pvsToUse;
      }
   }
}

5、总结:

循环依赖步骤: 

1)A类无参构造函数实例化后,设置三级缓存;

2)A类populateBean进行依赖注入,这里触发了B类属性的getBean操作;

3)B类无参构造函数实例化后,设置三级缓存;

4)B类populateBean进行依赖注入,这里触发了A 类属性的getBean操作;

5)A类之前正在实例化,singletonsCurrentlyInCreation集合中有已经有这个A类了,三级缓存里面也有了,所以这时候是从三级缓存中拿到的提前暴露的A实例,该实例还没有进行B类属性的依赖注入的,B类属性为空;

6)B类拿到了A的提前暴露实例注入到A类属性中了;

7)B类实例化已经完成,B类的实例化是由A类实例化中B属性的依赖注入触发的getBean操作进行的,现在B已经实例化,所以A类中B属性就可以完成依赖注入了,这时候A类B属性已经有值了;

8)B类A属性指向的就是A类实例堆空间,所以这时候B类A属性也会有值了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值