Spring启动流程源码分析

Spring启动流程源码分析(xml方式)

Spring IOC 容器源码分析

Bean生命周期

启动流程

测试目录结构及代码

单独的测试类都是以“My+该类实现的接口”来命名的

public class Main{
    public static void main(String[] args){
        System.out.println("【容器开始初始化】");
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("【容器初始化完毕】");
        System.out.println("【获取bean】");
        Person person = (Person) applicationContext.getBean("person");
        System.out.println("【获取bean完毕】name="+person.getName());
        System.out.println("【关闭容器】");
        ((ClassPathXmlApplicationContext) applicationContext).close();
    }
}

public class Person implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean{
//省略代码
}

执行结果

【容器开始初始化】
实例化BeanFactoryPostProcessor
执行BeanFactoryPostProcessor接口的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法
实例化BeanPostProcessor
实例化InstantiationAwareBeanPostProcessor
执行InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation(Class<?> beanClass, String beanName)方法
执行bean的无参构造方法Person()
执行InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation(Object bean, String beanName)方法
执行InstantiationAwareBeanPostProcessor接口的postProcessProperties(PropertyValues pvs, Object bean, String beanName)方法
为bean属性赋值,name=xiaoming
为bean属性赋值,age=20
执行BeanNameAware接口的setBeanName(String name)方法,beanName=person
执行BeanFactoryAware接口的setBeanFactory(BeanFactory beanFactory)方法
执行BeanPostProcessor接口的postProcessBeforeInitialization(Object bean, String beanName)方法
执行InitializingBean接口的afterPropertiesSet()方法
执行用户自定义初始化方法init-method
执行BeanPostProcessor接口的postProcessAfterInitialization(Object bean, String beanName)方法
【容器初始化完毕】
【获取bean】
【获取bean完毕】name=xiaoming
【关闭容器】
执行DestructionAwareBeanPostProcessor接口的postProcessBeforeDestruction(Object bean, String beanName)方法
执行DisposableBean接口的destroy()方法
执行用户自定义销毁方法destroy-method

流程分析

首先调用ClassPathXmlApplicationContext的构造方法

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
   this(new String[] {configLocation}, true, null);
}

public ClassPathXmlApplicationContext(
    String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
    throws BeansException {

    //设置父容器,这里parent为null
    super(parent);
    //将传入的配置文件路径存入成员变量String[] configLocations中
    setConfigLocations(configLocations);
    if (refresh) {
        //刷新容器
        refresh();
    }
}

Spring的启动流程几乎都在refresh()方法中

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 设置启动日期和一些标志位,初始化Environment,默认为StandardEnvironment
      prepareRefresh();

      // 刷新BeanFactory,如果之前存在则销毁,不存在则创建
      // 在这里会加载配置文件中的BeanDefinition并保存到beanFactory的Map中
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 配置BeanFactory,比如设置类加载器或添加一些BeanPostProcessor
      prepareBeanFactory(beanFactory);

      try {
         // 可被子类重写的回调,默认空实现
         postProcessBeanFactory(beanFactory);

         // 实例化并有序的调用实现BeanFactoryPostProcessor接口bean的对应方法
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

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

         // Last step: publish corresponding event.
         finishRefresh();
      }

      catch (BeansException ex) {
         //省略代码
         //当出现异常时移除所有缓存的bean并停止刷新工厂
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

刷新/创建beanFactory

对应refresh()方法中

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

obtainFreshBeanFactory()中调用了refreshBeanFactory()方法

protected final void refreshBeanFactory() throws BeansException {
   //刷新容器之前存在beanFactory则销毁
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      //直接new一个DefaultListableBeanFactory
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      //配置是否允许重复beanName的bean被覆盖、是否允许循环引用,默认都是允许
      customizeBeanFactory(beanFactory);
      //加载bean定义信息
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

loadBeanDefinitions(beanFactory)加载beanDefinition的主要步骤如下:

  • 先创建XmlBeanDefinitionReaderBeanDefinitionReader接口实现类之一)用来从xml配置文件中读取配置信息,并对BeanDefinitionReader进行相关的配置,如设置Environment等。
  • 依据配置文件所在位置将其转换为Resource,获取流之后使用DOM解析xml获取Document。对于<bean></bean>标签来说,会先解析该节点的各种属性,如id、name、class等信息,并将其封装为BeanDefinition,然后把所有的BeanDefinition以beanName为key保存到Map中,如果有别名则将beanName和alias的对应关系保存到对应的Map中(SimpleAliasRegistry类的aliasMap属性是一个ConcurrentHashMap,保存别名和规范名的映射)。对于其他标签如<aop:aspectj-autoproxy/>,则通过NamespaceHandler(这个标签是通过AopNamespaceHandler来解析标签)来解析特定命名空间标签的各种标签。

至此,beanFactory中已经加载了配置文件中所有的bean,还有一些Spring注入的bean(beanName为org.springframeworkXXXXX)。此时ApplicationContext中的BeanFactory包含的BeanDefinition信息如下:

配置BeanFactory的相关特性

对应refresh()方法中

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

这一步会对BeanFactory做一些配置以满足使用需求,比如配置ClassLoader等,同时也会先添加几个BeanPostProcessor用来处理实现声明周期接口的bean(即实现了XXXAware接口)或者用来探测接收事件的Listener,然后添加一些与Environment相关的bean到容器中。这里添加了两个BeanPostProcessor

实例化并有序的调用BeanFactoryPostProcessor

对应refresh()方法中

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

总体上就是:分类->排序->注册->执行

根据规定的bean生命周期,所有BeanDefinition都被加载到容器中之后,会先实例化并调用实现了BeanFactoryPostProcessor接口的bean的对应方法,实现了BeanFactoryPostProcessor接口的bean可以对已经加载到容器中的BeanDefinition做修改。

这里总体上分为两部分,一部分是对实现BeanDefinitionRegistryPostProcessor接口的有序调用,另一部分是对实现BeanFactoryPostProcessor接口的有序调用。

BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,是对其父类的扩展,主要强调对BeanDefinition的添加操作,因此在大的执行顺序上来说应该先将额外的BeanDefinition添加到容器中,在加载完所有需要的BeanDefinition后才应该执行对BeanDefinition的修改操作,主要是为了避免修改容器中还未加载进来的BeanDefinition的情况,所以执行顺序上应该有所保证。

流程如下:

  • 找出容器中实现BeanDefinitionRegistryPostProcessor接口的bean。
    • 在这些bean中找出实现了PriorityOrdered接口的bean,实例化并依据指定的优先级顺序执行。
    • 再找出实现了Ordered接口的bean,实例化并依据指定的优先级顺序执行。
    • 将剩下的bean实例化并执行此接口对应的方法。
    • 调用上述所有处理过的bean的BeanFactoryPostProcessor接口对应的方法,因为BeanDefinitionRegistryPostProcessor接口继承了BeanFactoryPostProcessor,所以实现子接口的bean必须实现父接口定义的方法。
  • 找出实现BeanFactoryPostProcessor接口的bean,并且是没有在上一步处理过的,即找出只实现了BeanFactoryPostProcessor接口的bean。下面的步骤类似上一步。
    • 实例化并有序的执行实现了PriorityOrdered接口的bean。
    • 实例化并有序的执行实现了Ordered接口的bean。
    • 实例化并执行剩余的bean。

至此,容器中所有实现了BeanFactoryPostProcessor接口的bean已经全部实例化并调用完毕。控制台输出如下:

【容器开始初始化】
实例化BeanFactoryPostProcessor
执行BeanFactoryPostProcessor接口的postProcessBeanFactory()方法

可以看出执行完又添加了一个BeanPostProcessor

实例化并有序的注册BeanPostProcessor

对应refresh()方法中

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

分类->排序->注册,大体上类似上一步。由于是分批次注册BeanPostProcessor,因此前一批BeanPostProcessor注册到容器后,再注册后一批的BeanPostProcessor时会应用前一批注册的BeanPostProcessor

先将所有实现了BeanPostProcessor接口的bean找出来,并将其分为三类:

  • 实现PriorityOrdered接口的bean
  • 实现Ordered接口的bean
  • 其他

然后将他们排序后存到beanFactory的List中(由图可知是保存到beanFactory中的CopyOnWriteArrayList中),线程安全且保证了将来的执行顺序。控制台输出如下:

实例化BeanPostProcessor
实例化DestructionAwareBeanPostProcessor
实例化InstantiationAwareBeanPostProcessor

可以看出此时的beanPostProcessors中包含8个BeanPostProcessor

初始化MessageSource消息源

对应refresh()方法中

// Initialize message source for this context.
initMessageSource();

如果父容器中已经定义了MessageSource则使用父容器定义的MessageSource,如果父容器未指定则创建默认的空的MessageSource实现。

初始化EventMulticaster事件多播器

对应refresh()方法中

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

如果之前已经向容器内添加了beanName为applicationEventMulticaster并且实现了ApplicationEventMulticaster接口的bean,则将该bean设置为当前容器的事件多播器,否则创建默认的事件多播器,默认为SimpleApplicationEventMulticaster

注册Listener监听器

对应refresh()方法中

// Check for listener beans and register them.
registerListeners();

将静态指定的ApplicationListener和容器中实现了ApplicationListener接口的bean作为监听器(Listener)添加到刚才初始化的事件多播器applicationEventMulticaster中,如果在这之前添加了earlyApplicationEvents也就是早期事件,则此时先把这些事件多播给对应的ApplicationListener监听器。多播事件的实现其实就是找到容器里的所有Listener,通过for循环调用每一个ListeneronApplicationEvent(event)方法。同时这也是观察者模式Spring中的一个应用。

实例化其余所有非懒加载的单例bean

对应refresh中

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

在这个方法中会实例化容器中所有非懒加载的单例bean。

首先,会对容器中所有的beanName遍历,调用getBean(beanName)方法,其中真正的逻辑在doGetBean()中。在此方法中,首先会调用getSingleton()方法尝试从容器中直接获取该bean。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   //首先从一级缓存中尝试获取,一级缓存中保存的是完全实例化后的bean,即已经实例化+初始化
   Object singletonObject = this.singletonObjects.get(beanName);
   //如果没找到且需要的bean正在创建中,即所需要的bean已经实例化但未填充属性,说明发生了循环依赖
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         //尝试从二级缓存中获取
         singletonObject = this.earlySingletonObjects.get(beanName);
         //如果二级缓存中没有并且允许获取提前引用的话
         if (singletonObject == null && allowEarlyReference) {
            //尝试从三级缓存中获取,三级缓存中保存的是用于创建指定bean提前引用的工厂
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               //调用工厂的方法获取该bean的提前引用
               singletonObject = singletonFactory.getObject();
               //将提前引用放入二级缓存,以后可能会用得到
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return singletonObject;
}

如果getSingleton()方法返回null则说明容器中还没有此bean的实例,则会尝试去父容器内找,如果还没找到的话则需要进行实例化。实例化之前会将该beanName存入alreadyCreated集合中,表示这个bean正在被创建或已经被创建。然后会调用getSingleton()方法并传入beanName和创建bean的逻辑(策略模式)。

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

getSingleton()方法中,会再次尝试从一级缓存中获取该bean,如果还是没获取到那么说明只能通过实例化来获取该bean了。注意创建单例bean需要对一级缓存加锁,即同一时间只能有一个线程执行单例bean的创建工作,但一个线程可以递归创建多个单例bean以解决循环依赖(可重入)。

在实例化bean之前会调用beforeSingletonCreation()方法将beanName加入到singletonsCurrentlyInCreation集合中,这个集合中保存正在创建中的beanName(一般是保存实例化但未填充属性的beanName,主要用于解决循环依赖问题),等bean实例化完成并填充、初始化等一系列操作全部完成后会把该beanName从singletonsCurrentlyInCreation集合中移除,代表此bean真正完成了初始化,可以被直接使用。

getSingleton()方法里会调用singletonFactory.getObject()方法,也就是之前传进来的创建bean的逻辑(就是那个传进来的Lambda表达式),实际会调用createBean()方法。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        //尝试从一级缓存中获取该bean
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            //标记该bean正在创建
            beforeSingletonCreation(beanName);
            try {
                //创建对象,实际调用createBean()方法
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            //...
            finally {
                //取消标记,表明当前bean创建完成
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                //将该bean注册到容器的Map中
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

createBean()方法中,会依据Class全限名使用Class.forName()得到Class对象,然后在实例化bean之前,也就是在调用bean的构造方法之前,会调用InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法,在这个方法中允许返回一个bean实例直接被程序使用而不会执行原来bean的构造方法等一系列操作,如果此方法返回null的话才开始实例化该bean。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    //获取该bean的Class
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        // 调用容器中InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法
        // 可以在这个方法中返回bean对象直接给程序使用,而不用经历后面bean的实例化、填充属性等操作
        // 即在这里可以直接返回bean对象的代理
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    try {
        //真正实例化bean对象 调用构造方法生成实例并填充属性
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
}

执行完resolveBeforeInstantiation(beanName, mbdToUse)方法,控制台就会打印:

beanName:a,执行InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法

实例化、填充属性等操作都是在doCreateBean()方法中完成的。首先调用createBeanInstance()方法,这个方法主要是拿到该bean的构造器,然后反射调用构造方法获得该bean的实例,然后会调用MergedBeanDefinitionPostProcessor接口的方法(在使用@Autowired时,这里调用的是AutowiredAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition()方法,查找该bean中的字段上是否包含@Autowired或者@Value,若包含则将注解信息封装为元信息InjectionMetadata保存到Map中,元信息中描述了要对哪个类的哪个字段进行注入)。然后会调用addSingletonFactory()方法将生产该bean提前引用的工厂存入三级缓存中,之后会解决一些循环依赖产生的问题。

对于循环引用来说,考虑两种情况:

  1. 如果当前bean与自身产生循环依赖(自己依赖自己),且需要用代理对象来代替原始bean时:

    实例化当前bean后同样会将生产该bean提前引用的工厂保存在三级缓存中,然后会填充属性。因为是自己依赖自己,所以会调用beanFactory.getBean()方法寻找需要的bean(自己找自己),因此会调用三级缓存中工厂的getObject()方法获取提前引用,并将引用转移到二级缓存。这里需要保证调用getObject()方法获取的对象应该是代理对象,因此调用getObject()方法时,也就是说调用getEarlyBeanReference()方法时,会调用SmartInstantiationAwareBeanPostProcessor接口的getEarlyBeanReference()方法,因此可以在这个接口的方法中创建一个代理对象并返回,这样就可以保证即使发生了循环依赖但获取的对象还是代理对象而不是原始对象本身。

  2. 如果当前bean与其他bean产生循环依赖,同样需要使用当前对象的代理对象时:

    假设A、B相互依赖,A填充属性时会实例化B,B填充属性时会拿到产生A提前引用的工厂,然后生产A的代理对象并保存到二级缓存(这里同样要保证getObject()返回的是代理对象,处理方式同上,实现SmartInstantiationAwareBeanPostProcessor接口并在其回调方法中创建代理对象并返回即可)。B创建结束,回到A继续执行,调用getSingleton(beanName, false)方法会得到之前保存到二级缓存的代理对象,如果initializeBean()方法没有返回代理对象则会将二级缓存中的代理对象作为最终使用的对象。

其实,如果需要使用代理对象的这种情况,一般会在initializeBean()方法中(也就是BeanPostProcessor接口对应的方法中)直接返回代理对象,而实现SmartInstantiationAwareBeanPostProcessor接口是为了保证发生循环依赖时拿到的提前引用也是代理对象。如果只在initializeBean()方法中返回代理对象,则发生循环依赖时注入的会是原始对象而不是代理对象;如果只实现SmartInstantiationAwareBeanPostProcessor接口并在对应方法中返回代理对象,那么当没有发生循环依赖时,容器中保存的单例bean将会是原始对象。因此想要使用代理对象必须两种情况都要考虑。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    throws BeanCreationException {
    //调用bean的构造器实例化该bean 例如本实例中执行到这里会打印:“实例化A”
    instanceWrapper = createBeanInstance(beanName, mbd, args);
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            // ApplicationListenerDetector在这里会查看是否该bean实现了ApplicationListener接口,若实现了则保存其beanName
            // AutowiredAnnotationBeanPostProcessor在这里会分析并保存注解的元数据信息,后面属性注入时处理@Autowired使用
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        }
    }
    // 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) {
        //将生产该bean提前引用的工厂存入三级缓存,这里其实也是策略模式
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        //为bean填充属性
        populateBean(beanName, mbd, instanceWrapper);
        //执行一系列初始化方法,可能会返回代理对象
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    // 判断当前bean是否正在被创建并且允许循环依赖
    if (earlySingletonExposure) {
        // 遍历一、二级缓存查找bean,其实只能在二级缓存中有可能找到
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            // 如果调用initializeBean()后返回的还是原始对象的话则将在二级缓存中获取的提前引用返回
            // 这里主要是判断initializeBean()方法是否产生了代理对象
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            //...
        }
    }

    // Register bean as disposable.
    try {
        //注册实现DisposableBean接口的bean
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    return exposedObject;
}

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

populateBean()方法用于为bean填充属性值。在为bean填充属性之前会先调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation()方法,如果该方法返回false,则不会为bean填充xml中指定的属性值而是直接return结束填充属性的操作。返回true则继续执行属性填充操作。

如果在之前的postProcessAfterInstantiation()方法中返回true,那么就会遍历容器中的所有InstantiationAwareBeanPostProcessor并调用接口对应的postProcessProperties()方法,在这里可以对xml里指定的属性值进行修改(如果使用注解的话会在这里处理@Autowired注解,找到所需的bean并注入,如果所需的bean没被实例化则先执行该bean的实例化操作,最终使用beanFactory.getBean()实现)。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw){
    // ...
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 如果这里返回false则不继续执行后面的属性填充操作
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    return;
                }
            }
        }
    }
    // ...
    // postProcessAfterInstantiation()全部返回true才能走到这里
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 可以在这里返回新的PropertyValues覆盖旧值(旧值可能是xml里配置的属性值)
            // @Autowired在这里处理 看下面的分析
            PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            // 如果在postProcessProperties()方法中返回null则调用接口的default方法进行处理
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                // 此方法是InstantiationAwareBeanPostProcessor接口的default方法
                pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
    //...
    //这里的PropertyValues可能是上面修改过的也可能是原始xml中配置的
    if (pvs != null) {
        //将属性值赋给bean的对应成员变量上
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

在上一步的populateBean()方法中会调用AutowiredAnnotationBeanPostProcessorpostProcessProperties()方法处理字段上的@Autowired注解。这里大体上分为两步:查找注解元数据和进行属性注入。

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 根据beanName等参数寻找注解元数据InjectionMetadata
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 进行属性注入
        metadata.inject(bean, beanName, pvs);
    }
    // ...
    return pvs;
}

findAutowiringMetadata()方法中,首先会根据传入的beanName等构造cacheKey用来查找对应的注解元信息。对于本例来说,某一时刻的注解元数据Map如下:

找到对应的注解元数据后就会进行属性注入,会一步步走到findAutowireCandidates()方法中,在这里会先根据依赖的类型查找对应的beanName,然后调用resolveCandidate()方法根据beanName查找对应的bean实例,最终还是通过调用beanFactory.getBean(beanName)来完成。实例化bean的过程从getBean()开始,在处理@Autowired注解时为了获取依赖对象又递归调用了getBean()

获取到需要的依赖bean对象后,在inject(bean, beanName, pvs)方法中通过反射为对象注入依赖。

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    // ...
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}

再回到populateBean()方法中,最后在applyPropertyValues()方法中会先拿到用户自定义类型转换器TypeConverter,如果没有则使用默认值。然后会调用resolveValueIfNecessary()方法解析当前属性依赖的值。

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    // 如果BeanPostProcessor没向PropertyValues中添加值,则不需要将PropertyValues中的值注入到bean,直接返回
    if (pvs.isEmpty()) {
        return;
    }
    if (pvs instanceof MutablePropertyValues) {
        mpvs = (MutablePropertyValues) pvs;
        //之前已经转换过了则可以直接为变量赋值
        if (mpvs.isConverted()) {
            // Shortcut: use the pre-converted values as-is.
            try {
                bw.setPropertyValues(mpvs);
                return;
            }
        }
        original = mpvs.getPropertyValueList();
    }
    else {
        original = Arrays.asList(pvs.getPropertyValues());
    }
	// 获取用户自定义类型转换器
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

    // Create a deep copy, resolving any references for values.
    List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    boolean resolveNecessary = false;
    for (PropertyValue pv : original) {
        // ...
        // 依据xml中配置的属性值类型做不同的解析操作
        // xml里配置的常量、其他bean引用等都会在这里解析
        Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
        
        // 在isWritableProperty()方法中会分析当前bean的信息,包括bean的所有属性、方法等全部描述信息
        // 是通过Introspector.getBeanInfo(beanClass)方法完成的
        // beanInfo中封装了bean中每个属性对应的set、get方法(如果存在的话),为后来的反射调用做准备
        boolean convertible = bw.isWritableProperty(propertyName) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
        //做一些变量的类型转换
        if (convertible) {
            convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
        }
        // 将转换后的值存入list中
        // ...
    }
    // Set our (possibly massaged) deep copy.
    try {
        // 通过反射调用setXXX()方法为变量赋值
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
}

resolveValueIfNecessary()方法中,会判断需要注入的属性值是什么类型的,每种类型对应不同的解析方法。如果当前bean需要注入其他bean,则会调用resolveReference()方法,首先会判断依赖的bean是否属于父容器,如果属于则去父容器中获取依赖的bean,否则会调用beanFactory.getBean()方法获取依赖的bean(如果发生了循环引用则会在这里转去执行依赖的bean的实例化等操作,整个过程类似递归)。

public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
    // We must check each value to see whether it requires a runtime reference
    // to another bean to be resolved.
    // 注入其他bean的引用
    if (value instanceof RuntimeBeanReference) {
        RuntimeBeanReference ref = (RuntimeBeanReference) value;
        return resolveReference(argName, ref);
    }
    // ...
    // xml直接注入常量
    else if (value instanceof TypedStringValue) {
        // Convert value to target type here.
        TypedStringValue typedStringValue = (TypedStringValue) value;
        Object valueObject = evaluate(typedStringValue);
        try {
            Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
            if (resolvedTargetType != null) {
                return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
            }
            else {
                return valueObject;
            }
        }
    }
}

解析完需要注入的属性值之后最后会调用setValue()方法,依旧是利用反射调用属性对应的setXX()方法将值设置为之前解析后的值。

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) {
        //...
    }
    else {
        ReflectionUtils.makeAccessible(writeMethod);
        //调用之前分析的属性对应的setXXX()方法
        writeMethod.invoke(getWrappedInstance(), value);
    }
}

回到之前的doCreateBean()方法,填充属性完成之后会调用initializeBean()方法,在该方法中首先会调用invokeAwareMethods()方法,为该bean注入容器内组件(如果该bean实现了XXXAware接口的话),然后会调用BeanPostProcessor接口的postProcessBeforeInitialization()方法。如果该bean实现了InitializingBean接口或在xml中定义了init-method的话,则会接着执行InitializingBean接口的afterPropertiesSet()方法和用户指定的init-method方法。最后调用BeanPostProcessor接口的postProcessAfterInitialization()方法。

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        //...
    }
    else {
        // 1.为bean注入容器内组件 即调用bean实现的XXXAware接口的对应方法
        invokeAwareMethods(beanName, bean);
    }
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 2.初始化前调用BeanPostProcessor接口的初始化前处理方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
        // 3.调用InitializingBean接口的方法和用户指定的init-method方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 4.初始化后调用BeanPostProcessor接口的初始化后处理方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

private void invokeAwareMethods(final String beanName, final Object bean) {
    // 如果该bean实现了XXXAware接口
    if (bean instanceof Aware) {
        // 根据实现的接口类型为bean注入指定属性
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            // ...
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

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

至此填充属性与初始化操作已全部结束,会将该bean注册到容器中,并从singletonsCurrentlyInCreation集合中移除,代表当前bean已经完全创建完毕可以直接使用,此时该bean处于容器的一级缓存中,可以通过beanFactory.getBean()直接获取。

为refresh收尾

对应refresh()

// Last step: publish corresponding event.
finishRefresh();
/**
 * Finish the refresh of this context, invoking the LifecycleProcessor's
 * onRefresh() method and publishing the
 * {@link org.springframework.context.event.ContextRefreshedEvent}.
 */
protected void finishRefresh() {
   // Clear context-level resource caches (such as ASM metadata from scanning).
   clearResourceCaches();

   // Initialize lifecycle processor for this context.
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}
  1. 清除之前缓存的资源
  2. 初始化LifecycleProcessor生命周期处理器。如果容器中已经存在了实现LifecycleProcessor接口的bean,则将该bean作为容器的LifecycleProcessor,在容器的各个生命周期会调用LifecycleProcessor的相关回调方法。如果不指定LifecycleProcessor实现类则使用默认的LifecycleProcessor实现类:DefaultLifecycleProcessor
  3. 调用LifecycleProcessoronRefresh()方法。
  4. 发布ContextRefreshedEvent事件。

IoC实现

Spring 的自动装配 → 骚话 @Autowired 的底层工作原理

处理@Autowired分为两个过程:

  1. 在bean实例化之后、调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation()方法之前,在MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition()方法中分析该bean的属性字段上是否存在@Autowired注解,构建注解元数据信息并保存,元数据中指明了哪个bean的哪个属性需要依赖注入,留作下一步使用。
  2. 在执行完InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation()方法之后,会调用InstantiationAwareBeanPostProcessor接口的postProcessProperties()方法,首先根据beanName查找对应的注解元数据InjectionMetadata,然后根据注解元数据为该bean注入依赖。

三级缓存及循环依赖

Spring 的循环依赖,源码详细分析 → 真的非要三级缓存吗

Spring如何解决循环依赖

/** 一级缓存保存完全初始化的bean。 Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 二级缓存保存从三级缓存中工厂制造出来的bean。 Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/** 三级缓存保存制造bean的工厂对象。 Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

举例:A依赖B,B依赖A。

首先通过getBean(A)发现一级缓存中没有已经初始化完毕的A对象并且A对象没有正在被创建(源码中的条件判断),因此走bean生命周期的初始化流程。实例化A后,会将可以产生A对象引用的工厂放入三级缓存中。若需要为A对象创建代理(比如启用的AOP并且A对象的某些方法匹配切点表达式)则该工厂会返回代理对象,否则该工厂返回刚才实例化后但未完成初始化的A对象。然后执行初始化操作为A对象的属性赋值,此时发现一级缓存中没有初始化完毕的B对象并且B也没有正在被创建,因此为B对象执行bean生命周期的初始化流程。在为B对象的属性赋值时,会先从一级缓存中查找A对象,因为A对象还没有完全初始化完毕,所以在一级缓存中不会找到A对象。根据源码中的条件判断可以发现A此时正在被创建(通过判断singletonsCurrentlyInCreation集合中是否包含当前bean的beanName),因此到二级缓存中查找,二级缓存中此时也没有A对象,因此到三级缓存中查找,此时得到之前放入的可以产生A对象的工厂,调用其getObject()方法获得还未完全初始化的A对象(也可能是代理对象),并将该对象放入二级缓存中,之后移除三级缓存中的工厂对象。

此时B已经完全初始化完毕,在getSingleton()方法的最后会将B对象添加至一级缓存中并移除二级缓存和三级缓存中对应的对象。最终回到为A填充属性的阶段,属性填充完毕后代表A也完成了所有的初始化工作,此时也将A对象添加至一级缓存并移除二级缓存和三级缓存中对应的对象。

关键源码

创建bean之前会先从各级缓存中查找该bean:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    // 一级缓存中没找到并且需要的bean正在被创建中,说明发生了循环依赖。
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 看看需要的bean是否在之前已经通过工厂产生了可以引用的对象(或代理对象)
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 工厂放入三级缓存后第一次被使用,则使用该工厂产生可以提前引用的对象
                    singletonObject = singletonFactory.getObject();
                    // 将产生的提前引用对象放入二级缓存,在该bean正式被放入一级缓存之前,二级缓存提供该bean的提前引用对象
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    // 提前引用已被生产并保存到二级缓存中,所以该工厂对象不再需要
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

实例化bean后执行初始化操作之前,会先将可以产生提前引用的工厂对象放入三级缓存中。

// 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) {
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
// ...
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            // 放入三级缓存
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}
// 用来获取提前引用的工厂对象
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;
                // 在AbstractAutoProxyCreator实现的getEarlyBeanReference()方法中会返回代理对象
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
    }
    return exposedObject;
}
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference
public Object getEarlyBeanReference(Object bean, String beanName) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    this.earlyProxyReferences.put(cacheKey, bean);
    // 根据切点表达式判断是否需要为当前bean产生代理对象
    return wrapIfNecessary(bean, beanName, cacheKey);
}

最后当所有初始化工作都完成后,将该bean放入一级缓存并清空二级缓存和三级缓存中对应的对象。

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        // 将初始化完毕的bean放入一级缓存
        this.singletonObjects.put(beanName, singletonObject);
        // 清除三级缓存中的工厂对象,若发生循环依赖则三级缓存中的工厂对象在之前就已经被移除
        this.singletonFactories.remove(beanName);
        // 清除二级缓存中的提前引用对象,若不发生循环依赖则二级缓存中不会产生当前bean的提前引用
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

AOP实现

通知(Advice或切面,例如@Before标注的方法)+ 切点(Pointcut,例如@Pointcut表示的表达式)= 增强器(Advisor)

首先在加载beanDefinition时,由AopNamespaceHandler中的AspectJAutoProxyBeanDefinitionParser来解析AOP相关的各种标签。在BeanDefinitionParserparse()方法中会向容器中注入beanName为internalAutoProxyCreatorBeanDefinition,对应类为AnnotationAwareAspectJAutoProxyCreator且实现了BeanPostProcessor,主要用来创建代理类。

在实例化并注册BeanPostProcessor时,会通过beanFactory.getBean()实例化AnnotationAwareAspectJAutoProxyCreator然后将其添加到容器中。在这之后通过调用beanFactory.getBean()方法实例化bean时,会调用AnnotationAwareAspectJAutoProxyCreatorpostProcessBeforeInstantiation()方法,在这里会遍历容器中的所有beanName,判断对应bean是否标有@Aspect注解。若该bean标有@Aspect注解则遍历其所有方法,分析方法上的注解,并将对应@Before@After等注解标注的方法封装为Advisor(实现类为InstantiationModelAwarePointcutAdvisorImplAdvisor中包含切点表达式和切面方法),加入Advisor缓存列表中,Advisor缓存列表位于BeanFactoryAspectJAdvisorsBuilder中。

产生代理的主要步骤都在BeanPostProcessorpostProcessAfterInitialization()接口中实现。首先从缓存中拿到所有的Advisor,然后通过反射遍历要创建的bean的所有方法,根据每个Advisor中的切点表达式判断该Advisor是否可以用于该bean。若表达式与之匹配则判断该bean是否实现了接口,若实现了接口则使用JDK动态代理(此时也可以根据标志位判断是否使用CGLIB),若没实现接口则直接使用CGLIB创建代理对象。

详细过程见下面文章:

Spring AOP 的实现过程

posted @   水渠过弯的AE86  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示