spring-beans包源码阅读-4-BeanFactory

欢迎光临我的个人博客:https://www.jelliclecat.cn/

前置

Spring阅读前言-里面讲了一些心路历程

spring-beans包源码阅读-2-BeanWrapper

spring-beans包源码阅读-3-BeanDefinition

终于到重点啦!由于BeanFactory太复杂了,这次我们会用单元测试调试跟踪源码。

一. BeanFactory和FactoryBean

先聊一聊BeanFactory和FactoryBean,期初我看源码的时候,看到这两个接口真是异常懵逼,他们的方法还很相似,都是获取一个Object。其实这两个接口八竿子打不着,九杆子能打着一点,这里就先讲一讲这两个接口各是干什么的。

1. BeanFactory

spring的总工厂,所有的bean的实例都保存在这个工厂中,并提供了各种不同的方法去获取各种的bean的实例。这个接口没啥好多说的,最核心的接口,等下我们会重点分析这个接口。

2. FactoryBean

从名字来看,首先这是一个Bean,然后这是一个工厂,其部分注释如下:

* If a bean implements this
* interface, it is used as a factory for an object to expose, not directly as a
* bean instance that will be exposed itself.
*
* 

NB: A bean that implements this interface cannot be used as a normal bean. * A FactoryBean is defined in a bean style, but the object exposed for bean * references ({@link #getObject()}) is always the object that it creates. public interface FactoryBean { @Nullable T getObject() throws Exception; ... }

FactoryBean才是真正的我们熟悉的"工厂方法模式",其实命名为Factory会更好,但是在spring中,所有的实体都是Bean,一个Factory也不例外是一个Bean,所以就命名为了FactoryBean。实现了这个接口的类就是一个工厂类,里面需要实现获取具体对象的逻辑。

3. FactoryBean,工厂方法模式

这里不会详细介绍什么是工厂模式,因为在进行spring源码阅读的时候会假定已经掌握了各种常用的设计模式。

那么FactoryBean是怎么使用工厂方法模式的呢?

FactoryBean有一个直接实现类:AbstractFactoryBean,里面实现了T getObject() throws Exception方法:

  /**
   * Expose the singleton instance or create a new prototype instance.
   * @see #createInstance()
   * @see #getEarlySingletonInterfaces()
   */
  @Override
  public final T getObject() throws Exception {
    if (isSingleton()) {
      return (this.initialized ? this.singletonInstance : getEarlySingletonInstance());
    }
    else {
      return createInstance();
    }
  }

  /**
   * Template method that subclasses must override to construct
   * the object returned by this factory.
   * 

Invoked on initialization of this FactoryBean in case of * a singleton; else, on each {@link #getObject()} call. * @return the object returned by this factory * @throws Exception if an exception occurred during object creation * @see #getObject() */ protected abstract T createInstance() throws Exception;

最后扔给了一个模板方法createInstance()去完成具体的实例的创建工作,这就是一个标准的工厂模式。

二. How getBean() works.

BeanFactory接口的集大成者就是DefaultListableBeanFactory,整个Bean的实例化过程、实例化策略等等内容,都在DefaultListableBeanFactory以及其父类AbstractAutowireCapableBeanFactory和AbstractBeanFactory中,故也是我们研究的重点对象。

image

这个继承关系也是没谁了。。

1. AliasRegistry & SimpleAliasRegistry

bean可能有各种别名,这个接口用来提供给一个Bean添加一些别名,并提供根据某个别名查找一个Bean的逻辑。所有的别名引用关系保存在一个map中,取的时候是递归算法:

  // SimpleAliasRegistry.java
  /**
   * Transitively retrieve all aliases for the given name.
   * @param name the target name to find aliases for
   * @param result the resulting aliases list
   */
  private void retrieveAliases(String name, List result) {
    this.aliasMap.forEach((alias, registeredName) -> {
      if (registeredName.equals(name)) {
        result.add(alias);
        retrieveAliases(alias, result);
      }
    });
  }

2. DefaultSingletonBeanRegistry

提供了保存单例Bean的Map、Set等集合,不仅仅是完全体的Bean,也有正在创建中的Bean,以及Bean之间的依赖关系都在这里。常说的"spring容器"中的容器,按我的理解就是这个类了。看看这个类的属性,就知道它的功能:

    /** Cache of singleton objects: bean name to bean instance. */
    private final Map singletonObjects = new ConcurrentHashMap<>(256);

    /** Cache of singleton factories: bean name to ObjectFactory. */
    private final Map> singletonFactories = new HashMap<>(16);

    /** Cache of early singleton objects: bean name to bean instance. */
    private final Map earlySingletonObjects = new HashMap<>(16);

    /** Set of registered singletons, containing the bean names in registration order. */
    private final Set registeredSingletons = new LinkedHashSet<>(256);

    /** Names of beans that are currently in creation. */
    private final Set singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    /** Names of beans currently excluded from in creation checks. */
    private final Set inCreationCheckExclusions =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    /** List of suppressed Exceptions, available for associating related causes. */
    @Nullable
    private Set suppressedExceptions;

    /** Flag that indicates whether we're currently within destroySingletons. */
    private boolean singletonsCurrentlyInDestruction = false;

    /** Disposable bean instances: bean name to disposable instance. */
    private final Map disposableBeans = new LinkedHashMap<>();

    /** Map between containing bean names: bean name to Set of bean names that the bean contains. */
    private final Map> containedBeanMap = new ConcurrentHashMap<>(16);

    /** Map between dependent bean names: bean name to Set of dependent bean names. */
    private final Map> dependentBeanMap = new ConcurrentHashMap<>(64);

    /** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
    private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

3. FactoryBeanRegistrySupport

这个类提供了对FactoryBean的支持,有一些bean不是直接创建的,而是通过FactoryBean工厂创建的,我们在上文讲过了FactoryBean。这个类的主要功能就是从FactoryBean中调用getObject方法拿到工厂创建出来的实例。

    /**
     * Obtain an object to expose from the given FactoryBean.
     * @param factory the FactoryBean instance
     * @param beanName the name of the bean
     * @return the object obtained from the FactoryBean
     * @throws BeanCreationException if FactoryBean object creation failed
     * @see org.springframework.beans.factory.FactoryBean#getObject()
     */
    private Object doGetObjectFromFactoryBean(final FactoryBean factory, final String beanName)
            throws BeanCreationException {

        Object object;
        try {
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    object = AccessController.doPrivileged((PrivilegedExceptionAction) factory::getObject, acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                // 就是这句,调用了FactoryBean的getObject()方法,拿到工厂创建的实例。
                object = factory.getObject();
            }
        }
 
 

很简单的一个类,不多讲了,这个类的代码也很简单,主要做了各种异常控制、权限检查、log打印,真正的关键代码只有object = factory.getObject();这一行。

4. AbstractBeanFactory & AbstractAutowireCapableBeanFactory

里面实现了BeanFactory中的核心方法:getBean

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

  /**
   * Return an instance, which may be shared or independent, of the specified bean.
   */
  protected  T doGetBean(final String name, @Nullable final Class requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
    ...

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

        // Guarantee initialization of beans that the current bean depends on.
        String[] dependsOn = mbd.getDependsOn();
        if (dependsOn != null) {
          for (String dep : dependsOn) {
            if (isDependent(beanName, dep)) {
              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
            }
            registerDependentBean(dep, beanName);
            try {
              getBean(dep);
            }
            catch (NoSuchBeanDefinitionException ex) {
              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
            }
          }
        }
    
        // Create bean instance.
        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);
        }
    ...
  }

前面如果设置了ParentBeanFactory,那么调用ParentBeanFactory去getBean。

先根据beanName拿到RootBeanDefinition,然后递归解析bean的所有依赖,朋友们可以想一下这个过程,最后保证当前所有的依赖都已经创建了,然后开始准备创建当前bean。

可以看到创建bean的工作委托给了createBean,这个方法在子类AbstractAutowireCapableBeanFactory中实现:

@Override
  protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
    ...
      // 真正创建bean的类
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    ...
  }

  protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {
    ... // 省略了其他代码
      instanceWrapper = createBeanInstance(beanName, mbd, args);
      populateBean(beanName, mbd, instanceWrapper);
      exposedObject = initializeBean(beanName, exposedObject, mbd);
    ...
  }

   /**
   * Initialize the given bean instance, applying factory callbacks
   * as well as init methods and bean post processors.
   * 

Called from {@link #createBean} for traditionally defined beans, * and from {@link #initializeBean} for existing bean instances. */ protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { 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; }

这里就非常清晰了:

首先委托给了真正的创建方法:doCreateBean

doCreateBean实例化Bean分三步走:

  1. doCreateBean中首先调用createBeanInstance实例化Bean,这个时候Bean被实例化了。createBeanInstance中根据各种不同的配置,采用不同的构造函数进行实例化。

  2. doCreateBean中然后调用populateBean方法,改方法将Bean的各种依赖通过BeanWrapper提供的对属性的编辑方法,设置到Bean中。这一步完成了Bean的依赖的组装。

  3. doCreateBean最后调用了initializeBean,意为初始化Bean,这个时候的Bean已经是一个Object实例,并且Bean中通过@Autowire设置的依赖也全部设置完毕。但是最后还有一些初始化工作要做,看代码:首先,如何这个Bean实现了各种Aware接口,则依次调用这些接口的set方法设置信息;然后调用所有的BeanPostProcessors中的Before方法;然后调用通过"init-method"指定的init方法;最后调用所有BeanPostProcessors中的After方法。

最后,这些方法一层一层向上返回了初始化完成的Bean实例。

返回到AbstractBeanFactory中后调用了getObjectForBeanInstance(),检查返回的Bean Instance是否是FactoryBean,如果是,则调用getObject方法获取真正的实例。

创建完后的Bean会放进各种Map中,前面已经讲过了,下次再次getBean的时候,就是从缓存中获取了。

三. 总结

我们没有讲Spring是怎么扫描并将各种标注了@Service的Class转换成BeanDefinition的,上面的过程是在所有的BeanDefinition已经生成并存储在内存中之后执行的。BeanFactory有一个实现类叫做XmlBeanFactory,虽然已经被遗弃了,但是里面展示了如何将application.xml中定义的Bean转化成BeanDefinition的过程,这些都不是这篇文章的重点。这篇文章重点讲解了BeanFactory的每一级继承结构,以及调用getBean的时候发生了什么,Bean的实例是如何被创建并返回的,Aware接口是什么时候被调用的。

在代码中我们可以清晰的看到一个bean被初始化的生命周期:实例化->组装各种依赖->调用Aware接口方法->调用BeanPostProcessor的before方法->指定的"init-method"方法->调用BeanPostProcessor的after方法。关于生命周期,《Spring In Action》这本书中有详细讲解。

其实到这里spring-beans模块的核心部分就已经讲完了,里面还有一些接口如:Aware、InitializingBean、DisposableBean、BeanReference等,这些都是常用接口,但是这些接口没啥好讲的,都是基于实践意义上的接口。关于RootBeanDefinition和ChildBeanDefinition是如何合并的这里也没有多说,比较简单,基于java的继承和多态机制仿的一个工能,所以也不说了。

之后可能会讲一讲spring-context包和spring-mvc包中的一些常用接口,但是我认为spring的灵魂部分,到这里算是讲完了。

其实究其本质呢,bean的初始化底层依赖两个工具,那就是反射和自省,用反射实例化Bean以及调用一些方法(如init-method),用自省去设置Bean的各种属性。中间做的各种工作,都是对这两个底层调用的封装,BeanWrapper就是对自省功能的封装,BeanDefinition是对Bean的设置,BeanFactory是对反射功能的封装。

除了spring的主体功能之外,还有异常的封装、log的打印等都是值得好好研究和学习的地方,以后有时间我也会给朋友们写一写。

如果文章中有任何不对的地方,请您不吝赐教,也欢迎加我微信交流~

欢迎光临我的个人博客:https://www.jelliclecat.cn/

你可能感兴趣的:(spring-beans包源码阅读-4-BeanFactory)