spring-自动装配(二)

375 阅读8分钟

除了可以通过自动装配的方式来注入自己定义的类实例,也可以注入spring容器底层的一些组件,比如ApplicationContext、BeanName、StringValueResolver等。这些组件的注入方式通过实现对应的XXXAware接口,来进行注入。

比如要想在自己定义的类当中使用ApplicationContext、BeanName、StringValueResolver,则相应的需要实现ApplicationContextAware、BeanNameAware、EmbeddedValueResolverAware接口,具体代码如下:

public class Dog implements InitializingBean, DisposableBean, ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {

    private ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Dog...setApplicationContext..." + applicationContext);
        this.applicationContext = applicationContext;
    }

    /**
     * 设置bean的名称
     * @param s
     */
    public void setBeanName(String s) {
        System.out.println("Dog...setBeanName..." + s);
    }


    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        System.out.println("Dog...setEmbeddedValueResolver...");
        String s = resolver.resolveStringValue("dog...${os.name}...#{20*18}");
        System.out.println(s);
    }
}

通过实现ApplicationContextAware的setApplicationContext方法,可以获得spring容器当中的ApplicationContext,通过实现BeanNameAware的setBeanName方法,可以获得该类的对象在容器当中的名称,通过实现EmbeddedValueResolverAware的setEmbeddedValueResolver方法,可以获得spring容器当中的StringValueResolver组件,通过该组件,可以处理一些字符串的逻辑,比如占位符、SPEL表达式等等。

在配置文件中配置Dog对应的bean:

@Configuration
public class SpringDIConfig {
    @Bean
    public Dog dog() {
        return new Dog();
    }

}

测试一些,获取对应的dog组件:

public class TestDI {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringDIConfig.class);
        Dog dog = applicationContext.getBean(Dog.class);
    }

}

控制台输出:

Dog...setBeanName...dog
Dog...setEmbeddedValueResolver...
dog...Windows 10...360

spring底层组件注入原理

那么spring是在什么时候怎么把这些底层组件注入到自定义的实例当中的呢?

以ApplicationContext注入为研究点,在setApplicationContext方法上设置断点,通过debug的方式启动测试。可以发现在启动容器时,会调用refresh方法:

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
   this();
   register(annotatedClasses);
   refresh();
}

在refresh方法中,进行了如下步骤:

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      //为刷新做上下文准备,预处理
      prepareRefresh();

      // 获取beanFactory bean工厂
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // bean工厂的预准备工作
      prepareBeanFactory(beanFactory);

      try {
         // bean工厂准备工作完成之后的后置处理工作
         postProcessBeanFactory(beanFactory);

         // 执行beanFactoryPostProcessor
         invokeBeanFactoryPostProcessors(beanFactory);

         // 注册BeanPostProcessor的各类组件
         registerBeanPostProcessors(beanFactory);

         // 初始化MessageSource组件
         initMessageSource();

         // 初始化事件派发器
         initApplicationEventMulticaster();

         // 初始化其他特殊的bean
         onRefresh();

         // 注册各个监听器
         registerListeners();

         // 完成容器当中其他剩下的单实例bean的初始化
         finishBeanFactoryInitialization(beanFactory);

         // 完成BeanFactory的初始化创建工作;IOC容器就创建完成
         finishRefresh();
      }

暂且不去看refresh前面的步骤,根据断点执行后产生的方法栈,定位到spring容器底层组件在bean当中的注入是在finishBeanFactoryInitialization(beanFactory)初始化对应的bean时进行注入的。继续往下看finishBeanFactoryInitialization(beanFactory)方法:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // ...

   // Instantiate all remaining (non-lazy-init) singletons.
   beanFactory.preInstantiateSingletons();
}

忽略该方法前面对BeanFactory的一些操作,直接进入最后一步实例化所有非懒加载的单实例:

public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }

   // 获取定义的bean工厂中定义的所有的bean名称
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // 遍历bean名称...
   for (String beanName : beanNames) {
      //根据bean名称获取对应的定义
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //只对非抽象、单实例、非懒加载的对象进行实例化
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         //判断是否工厂bean,如果是则进行相关的实例化操作
         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 {
            //如果不是工厂bean,则调用getBean方法进行实例化
            getBean(beanName);
         }
      }
   }

   // 其他操作...
}

spring在该步只会对非抽象、非懒加载的单实例进行实例化,而我们之前定义的Dog符合要求,并且不属于工厂bean所以,直接调用getBean进行实例化:

public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

进入doGetBean:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   //获取对应的bean名称
   final String beanName = transformedBeanName(name);
   Object bean;

   // 从缓存当中获取bean根据beanName,用于判断bean是否已经被创建
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      //日志操作
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      //获取对应的bean实例
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      // 如果正在创建该beanName的实例则直接抛出异常      
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // 检测这个bean是否在该工厂当中存在
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // 操作忽略...
      }

      //在实例化该对象之前,先标记该bean已被创建,避免多线程
      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }

      try {
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // 实例化该bean所依赖的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);
               }
            }
         }

         // 创建bean实例
         if (mbd.isSingleton()) {
            //如果是单实例,则调用createBean来创建对象
            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);
         }

         else if (mbd.isPrototype()) {
            // 如果是 prototype类型则创建一个新的实例 ...
         }
         else {
               //其他类型...
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   //其他步骤忽略...
   
   return (T) bean;
}

在创建bean之前会先根据bean的名称从缓存当中获取,如果能获取到说明该bean已经被创建过,并且被存在在了缓存当中,则直接取缓存当中的bean

// 从缓存当中获取bean根据beanName,用于判断bean是否已经被创建
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      //日志操作
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      //获取对应的bean实例
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

否则会继续创建bean的流程。获取bean的定义信息

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

获取该bean所有的依赖,如果有,则调用getBean()方法先创建出对应的所有依赖

        // 实例化该bean所依赖的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);
               }
            }
         }

最后启动单实例创建bean流程,createBean:

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

    //其他操作

    //创建bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);

    //其他操作
   
}

进入doCreateBean:

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

   // 获取bean的包装
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      //如果bean时单实例,则先从缓存中获取bean的包装
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
       //如果bean的包装为null,则通过工厂方法或者构造函数创建出对应的bean
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   //获取最终的bean实例
   final Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // postProcessors去修改实现了MergedBeanDefinitionPostProcessor的bean
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            //调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
            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.isTraceEnabled()) {
         logger.trace("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 {
      //拿到bean的各个属性值,用于下一步的初始化
      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);
      }
   }

   //其他操作

   return exposedObject;
}

该步骤先会创建出对应的bean实例,然后判断该bean是否为MergedBeanDefinitionPostProcessor的实现,如果是的话则执行调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法,接着会获取该对象的所有属性值,然后进入initializeBean方法进行属性赋值,这也是本篇所研究的spring底层组件注入的地方,接着往下看:

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 {
      //执行实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的类,调用对应的setXXX方法
      invokeAwareMethods(beanName, bean);
   }

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

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

第一步通过调用invokeAwareMethods方法来执行实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的类,调用对应的setXXX方法

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

接着执行后置处理器bean初始化之前的方法:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessBeforeInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}

此步进入,可以发现该方法内部会调用invokeAwareInterfaces

private void invokeAwareInterfaces(Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof EnvironmentAware) {
         ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
      }
      if (bean instanceof EmbeddedValueResolverAware) {
         ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
      }
      if (bean instanceof ResourceLoaderAware) {
         ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
      }
      if (bean instanceof ApplicationEventPublisherAware) {
         ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
      }
      if (bean instanceof MessageSourceAware) {
         ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
      }
      if (bean instanceof ApplicationContextAware) {
         ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
      }
   }
}

来执行EnvironmentAwareResourceLoaderAwareEmbeddedValueResolverAwareApplicationEventPublisherAwareMessageSourceAwareApplicationContextAware的XXXAware对应的setXXX方法,也就是说这些spring注解的注入是在此步进行的。

到此对于spring的底层组件的注入原理我们就分析完啦。