美文网首页Java成长之路
源码成神之路:Spring Framework源代码解析之IOC

源码成神之路:Spring Framework源代码解析之IOC

作者: 路人甲java | 来源:发表于2020-04-03 13:43 被阅读0次

    在Spring Framework源代码解析之IOC容器(一)和Spring Framework源代码解析之IOC容器(二),我们对Spring IOC做了简单介绍以及熟悉了一些支持IOC的关键类,本文将对IOC的依赖注入特性进行解析,欢迎指正。

    载入和注册

    在上文中,我们介绍到XmlBeanFactory对资源文件的载入,并最后引出了一个高帅富——ApplicationContext。接着上文来看,其实我们平时最常用的是Application,因为它不仅具备BeanFactory的全部能力,还为应用程序提供了很多的便利,上文已经说过了,它继承了很多父类,使它可以具备支持国际化、支持多方式定义资源,支持事件等。我们可以认为BeanFactory和Application是两个层面的IOC容器,而我们平时开发应用程序就是使用Application。Application有很多抽象子类,如AbstractApplicationContext,在该抽象子类下又有很多具体的实现类,如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext等。我们以FileSystemXmlApplicationContext为例,来看看它载入和注册资源的过程。

    首先通过FileSystemXmlApplicationContext来建立IOC容器:

    ApplicationContext = new FileSystemXmlApplicationContext(xmlPath);
    调用构造函数:

    /**

    • Create a new FileSystemXmlApplicationContext, loading the definitions
    • from the given XML files and automatically refreshing the context.
    • @param configLocations array of file paths
    • @throws BeansException if context creation failed
      */
      public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
      this(configLocations, true, null);
      }
      实际调用:

    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
    throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }
    

    注意方法refresh(),这里使用了一个“模板方法”的设计模式,refresh()是一个模板方法,具体实现在FileSystemXmlApplicationContext的若干级父类AbstractXmlApplicationContext中:

    public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
    synchronized (this.activeMonitor) {
    this.active = true;
    }

        // 这里需要子类来协助完成资源位置定义,bean 载入和向 IOC 容器注册的过程  
        refreshBeanFactory(); 
         ............ 
    

    }
    refresh()方法包含了整个IOC容器的初始化过程,资源的定位由refreshBeanFactory()来实现,而在AbstractXmlApplicationContext中定义了对资源的读取过程,默认由 XmlBeanDefinitionReader 来读取:

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
    // 这里使用 XMLBeanDefinitionReader 来载入 bean 定义信息的 XML 文件
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

     //这里配置 reader 的环境,其中 ResourceLoader 是我们用来定位 bean 定义信息资源位置的  
     ///因为上下文本身实现了 ResourceLoader 接口,所以可以直接把上下文作为 ResourceLoader 传递给 XmlBeanDefi
    

    nitionReader
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

     initBeanDefinitionReader(beanDefinitionReader); 
     //这里转到定义好的 XmlBeanDefinitionReader 中对载入 bean 信息进行处理 
     loadBeanDefinitions(beanDefinitionReader); 
    

    }
    转到beanDefinitionReader中进行处理:

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOExcepti
    on {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
    //调用 XmlBeanDefinitionReader 来载入 bean 定义信息。
    reader.loadBeanDefinitions(configResources);
    }
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
    reader.loadBeanDefinitions(configLocations);
    }
    }
    完成了载入,我们来分析注册,来到DefaultListableBeanFactory中,它通过HashMap来持有载入的BeanDefinition:

    /** Map of bean definition objects, keyed by bean name */
    private final Map<string ,="" beandefinition=""> beanDefinitionMap = new ConcurrentHashMap<string ,="" beandefinition="">();</string></string>
    跟踪代码,找到注册的具体实现类DefaultListableBeanFactoy:

    //---------------------------------------------------------------------
    // Implementation of BeanDefinitionRegistry interface
    //---------------------------------------------------------------------

    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
    
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
    
        synchronized (this.beanDefinitionMap) {
            //这里检查是不是有名字相同的BeanDefinition已经在IOC容器中注册,如果有但不允许覆盖则抛出异常
            Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
            if (oldBeanDefinition != null) {
                if (!this.allowBeanDefinitionOverriding) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                            "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                            "': There is already [" + oldBeanDefinition + "] bound.");
                }
                else {
                    if (this.logger.isInfoEnabled()) {
                        this.logger.info("Overriding bean definition for bean '" + beanName +
                                "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                    }
                }
            }
            else {
                this.beanDefinitionNames.add(beanName);
                this.frozenBeanDefinitionNames = null;
            }
            this.beanDefinitionMap.put(beanName, beanDefinition);
    
            resetBeanDefinition(beanName);
        }
    }
    

    完成了注册,此时我们就是从容器中使用对象了,万事具备只欠getBean了。

    依赖注入

    我们记得在BeanFactory中有一个getBean方法,它其实就是触发依赖注入的入口,getBean的实现我们具体看看DefaultListableBeanFactory的父类AbstractBeanFactory,看看其中getBean的是如何实现的:

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

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

      3:
      4: final String beanName = transformedBeanName(name);
      5: Object bean;
      6:
      7: // Eagerly check singleton cache for manually registered singletons.
      8: // 先从缓存里面取,处理已经被创建过的单件模式的bean,对这种bean的获取不需要重复的创建
      9: Object sharedInstance = getSingleton(beanName);
      10: if (sharedInstance != null && args == null) {
      11: if (logger.isDebugEnabled()) {
      12: if (isSingletonCurrentlyInCreation(beanName)) {
      13: logger.debug("Returning eagerly cached instance of singleton bean '"
      14: + beanName
      15: + "' that is not fully initialized yet - a consequence of a circular reference");
      16: } else {
      17: logger.debug("Returning cached instance of singleton bean '"
      18: + beanName + "'");
      19: }
      20: }
      21: bean = getObjectForBeanInstance(sharedInstance, name, beanName,
      22: null);
      23: }
      24:
      25: else {
      26: // Fail if we're already creating this bean instance:
      27: // We're assumably within a circular reference.
      28: if (isPrototypeCurrentlyInCreation(beanName)) {
      29: throw new BeanCurrentlyInCreationException(beanName);
      30: }
      31:
      32: // Check if bean definition exists in this factory.
      33: BeanFactory parentBeanFactory = getParentBeanFactory();
      34: if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
      35: // Not found -> check parent.
      36: String nameToLookup = originalBeanName(name);
      37: if (args != null) {
      38: // Delegation to parent with explicit args.
      39: return (T) parentBeanFactory.getBean(nameToLookup, args);
      40: } else {
      41: // No args -> delegate to standard getBean method.
      42: return parentBeanFactory
      43: .getBean(nameToLookup, requiredType);
      44: }
      45: }
      46:
      47: if (!typeCheckOnly) {
      48: markBeanAsCreated(beanName);
      49: }
      50: // 这里根据bean的名字取得BeanDefinition
      51: final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
      52: checkMergedBeanDefinition(mbd, beanName, args);
      53:
      54: // Guarantee initialization of beans that the current bean depends
      55: // on.
      56: // 取当前bean的所有依赖的bean,这样会触发getBean的递归调用,直至取到一个没有任何依赖的bean为止
      57: String[] dependsOn = mbd.getDependsOn();
      58: if (dependsOn != null) {
      59: for (String dependsOnBean : dependsOn) {
      60: getBean(dependsOnBean);
      61: registerDependentBean(dependsOnBean, beanName);
      62: }
      63: }
      64:
      65: // Create bean instance.
      66: // 这里创建单例的实例,调用createBean方法
      67: if (mbd.isSingleton()) {
      68: sharedInstance = getSingleton(beanName,
      69: new ObjectFactory<Object>() {
      70: public Object getObject() throws BeansException {
      71: try {
      72: return createBean(beanName, mbd, args);
      73: } catch (BeansException ex) {
      74: // Explicitly remove instance from singleton
      75: // cache: It might have been put there
      76: // eagerly by the creation process, to allow
      77: // for circular reference resolution.
      78: // Also remove any beans that received a
      79: // temporary reference to the bean.
      80: destroySingleton(beanName);
      81: throw ex;
      82: }
      83: }
      84: });
      85: bean = getObjectForBeanInstance(sharedInstance, name, beanName,
      86: mbd);
      87: }
      88: // 这里则是创建prototype bean的地方
      89: else if (mbd.isPrototype()) {
      90: // It's a prototype -> create a new instance.
      91: Object prototypeInstance = null;
      92: try {
      93: beforePrototypeCreation(beanName);
      94: prototypeInstance = createBean(beanName, mbd, args);
      95: } finally {
      96: afterPrototypeCreation(beanName);
      97: }
      98: bean = getObjectForBeanInstance(prototypeInstance, name,
      99: beanName, mbd);
      100: }
      101:
      102: else {
      103: String scopeName = mbd.getScope();
      104: final Scope scope = this.scopes.get(scopeName);
      105: if (scope == null) {
      106: throw new IllegalStateException(
      107: "No Scope registered for scope '" + scopeName + "'");
      108: }
      109: try {
      110: Object scopedInstance = scope.get(beanName,
      111: new ObjectFactory<Object>() {
      112: public Object getObject() throws BeansException {
      113: beforePrototypeCreation(beanName);
      114: try {
      115: return createBean(beanName, mbd, args);
      116: } finally {
      117: afterPrototypeCreation(beanName);
      118: }
      119: }
      120: });
      121: bean = getObjectForBeanInstance(scopedInstance, name,
      122: beanName, mbd);
      123: } catch (IllegalStateException ex) {
      124: throw new BeanCreationException(
      125: beanName,
      126: "Scope '"
      127: + scopeName
      128: + "' is not active for the current thread; "
      129: + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
      130: ex);
      131: }
      132: }
      133: }
      134:
      135: // Check if required type matches the type of the actual bean instance.
      136: // 这里对创建出来bean进行类型的检查,如果没有问题,就返回这个新创建的bean
      137: if (requiredType != null && bean != null
      138: && !requiredType.isAssignableFrom(bean.getClass())) {
      139: try {
      140: return getTypeConverter()
      141: .convertIfNecessary(bean, requiredType);
      142: } catch (TypeMismatchException ex) {
      143: if (logger.isDebugEnabled()) {
      144: logger.debug(
      145: "Failed to convert bean '" + name
      146: + "' to required type ["
      147: + ClassUtils.getQualifiedName(requiredType)
      148: + "]", ex);
      149: }
      150: throw new BeanNotOfRequiredTypeException(name, requiredType,
      151: bean.getClass());
      152: }
      153: }
      154: return (T) bean;
      155: }
      具体创建对象在createBean里面,来看看createBean:

      1: protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
      2: throws BeanCreationException {
      3:
      4: if (logger.isDebugEnabled()) {
      5: logger.debug("Creating instance of bean '" + beanName + "'");
      6: }
      7: // Make sure bean class is actually resolved at this point.
      8: resolveBeanClass(mbd, beanName);
      9:
      10: // Prepare method overrides.
      11: try {
      12: mbd.prepareMethodOverrides();
      13: }
      14: catch (BeanDefinitionValidationException ex) {
      15: throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
      16: beanName, "Validation of method overrides failed", ex);
      17: }
      18:
      19: try {
      20: // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      21: Object bean = resolveBeforeInstantiation(beanName, mbd);
      22: if (bean != null) {
      23: return bean;
      24: }
      25: }
      26: catch (Throwable ex) {
      27: throw new BeanCreationException(mbd.getResourceDescription(), beanName,
      28: "BeanPostProcessor before instantiation of bean failed", ex);
      29: }
      30: //这里是创建bean的调用
      31: Object beanInstance = doCreateBean(beanName, mbd, args);
      32: if (logger.isDebugEnabled()) {
      33: logger.debug("Finished creating instance of bean '" + beanName + "'");
      34: }
      35: return beanInstance;
      36: }
      又看doCreateBean,_遭不住啊。。

      1: protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
      2: // Instantiate the bean.
      3: BeanWrapper instanceWrapper = null;
      4: if (mbd.isSingleton()) {
      5: instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
      6: }
      7: if (instanceWrapper == null) {
      8: instanceWrapper = createBeanInstance(beanName, mbd, args);
      9: }
      10: .........
      11:
      12: }
      具体创建对象的方法是createBeanInstance:

      1: protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
      2: // Make sure bean class is actually resolved at this point.
      3: Class beanClass = resolveBeanClass(mbd, beanName);
      4:
      5: if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      6: throw new BeanCreationException(mbd.getResourceDescription(), beanName,
      7: "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
      8: }
      9: //这里使用工厂方法对bean进行实例化
      10: if (mbd.getFactoryMethodName() != null) {
      11: return instantiateUsingFactoryMethod(beanName, mbd, args);
      12: }
      13:
      14: // Shortcut when re-creating the same bean...
      15: boolean resolved = false;
      16: boolean autowireNecessary = false;
      17: if (args == null) {
      18: synchronized (mbd.constructorArgumentLock) {
      19: if (mbd.resolvedConstructorOrFactoryMethod != null) {
      20: resolved = true;
      21: autowireNecessary = mbd.constructorArgumentsResolved;
      22: }
      23: }
      24: }
      25: if (resolved) {
      26: if (autowireNecessary) {
      27: return autowireConstructor(beanName, mbd, null, null);
      28: }
      29: else {
      30: return instantiateBean(beanName, mbd);
      31: }
      32: }
      33:
      34: // Need to determine the constructor...
      35: //使用构造函数进行实例化
      36: Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
      37: if (ctors != null ||
      38: mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
      39: mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      40: return autowireConstructor(beanName, mbd, ctors, args);
      41: }
      42:
      43: // No special handling: simply use no-arg constructor.
      44: //使用默认的构造函数对bean进行实例化
      45: return instantiateBean(beanName, mbd);
      46: }
      来看看使用默认的构造函数对bean进行实例化的代码instantiateBean:

      1: protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
      2: try {
      3: //使用默认的实例化策略对bean进行实例化,默认的实例化策略是CglibSubclassingInstantiationStrategy,也就是用cglib来对bean进行实例化
      4: Object beanInstance;
      5: final BeanFactory parent = this;
      6: if (System.getSecurityManager() != null) {
      7: beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
      8: public Object run() {
      9: return getInstantiationStrategy().instantiate(mbd, beanName, parent);
      10: }
      11: }, getAccessControlContext());
      12: }
      13: else {
      14: beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      15: }
      16: BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      17: initBeanWrapper(bw);
      18: return bw;
      19: }
      20: catch (Throwable ex) {
      21: throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
      22: }
      23: }
      这里用cglib对bean进行实例化,cglib是一个常用的字节码生成器的类库,它提供了一系列的API来提供java字节码生成和转换的功能,如果有兴趣可以查看cglib的使用文档。另外生成bean的策略还有很多种,这里只是选了最常用的方法来介绍。至此,bean实例创建过程就算完成了,然后通过populateBean方法将创建好的实例的依赖关系设置好,最终完成依赖注入的过程,由于篇幅关系这里就不详细列举了,populateBean方法可以在AbstractAutowireCapableBeanFactory中找到。

    小结

    自己对Spring IOC代码的学习暂时就到这里,要搞懂一个特性,确实需要花费很大的功夫,Spring代码量比较大,而且各个特性之间又有交叉,要梳理清楚不是件容易的事,不过回头来看自己还是有收获的,希望对看它的朋友也有一点收获。

    注意注意:以上分享的这些Spring笔记:面试锦集解析+学习笔记+学习导图+Spring源码视频,如果你想要一起学习转发后关注我私信【资料】免费领取吧

    相关文章

      网友评论

        本文标题:源码成神之路:Spring Framework源代码解析之IOC

        本文链接:https://www.haomeiwen.com/subject/twehphtx.html