Spring技术内幕-第二章-IoC容器的实现-3、IoC容器的依赖注入

IoC容器的依赖注入

前面的两篇博客对IoC容器的初始化进行了详细的分析,这个初始化过程完成的主要的工作是在IoC容器中建立BeanDefinition数据映射,在这个过程中并没有看到IoC容器对Bean依赖关系进行注入,接下来分析一下IoC容器是怎么样对Bean的依赖关系进行注入的。

假设当前IoC容器已经载入了用户定义的Bean信息,开始分析依赖注入的原理。首先,注意到依赖注入的过程是用户第一次向IoC容器所要Bean的时候触发的,当然也有例外,也就是我们可以在BeanDefinition信息中通过lazy-init属性来让容器完成对Bean的预实例化。

这个预实例化实际上也是一个完成依赖注入的过程,但是它是在初始化的过程中完成的。BeanFactory的getBean就是触发依赖注入发生的地方。

下面从DefaultListableBeanFactory的基类AbstractBeanFactory入手去看看getBean的实现。

//这里是对BeanFactory接口的实现,比如getBean接口方法
//这些getBean接口方法最终是通过调用doGetBean来实现的。
public Object getBean(String name) throws BeansException 
{
    return this.doGetBean(name, (Class)null, (Object[])null, false);
}

public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    return this.doGetBean(name, requiredType, (Object[])null, false);
}

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

public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
    return this.doGetBean(name, requiredType, args, false);
}



//这里是实际获取Bean的地方,也是触发依赖注入发生的地方
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException
{
    final String beanName = this.transformedBeanName(name);
    //先从缓存中取得Bean,处理那些已经被创建过的单例模式的Bean,对这种Bean的请求不需要重复的创建
    Object sharedInstance = this.getSingleton(beanName);
    Object bean;
    if (sharedInstance != null && args == null)
    {
        if (this.logger.isDebugEnabled())
        {
            if (this.isSingletonCurrentlyInCreation(beanName))
            {
                this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else
            {
                this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        //这里的getObjectForBeanInstance完成的是FactoryBean的相关处理,以取得FactoryBean的生产关系
        //BeanFactory和FactoryBean的区别在前面讲过,这个过程在后面还会详细的分析。
        bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
    }
    else
    {
        if (this.isPrototypeCurrentlyInCreation(beanName))
        {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        //这里对IoC的BeanDefinition是否存在进行检查,检查是否能在当前的BeanFactory中取得需要的Bean,如果在当前的工厂中
        //取不到,则到双亲BeanFactory中去取,如果当前的双亲工厂取不到,那就顺着双亲BeanFactory链向上查找。
        BeanFactory parentBeanFactory = this.getParentBeanFactory();
        if (parentBeanFactory != null && !this.containsBeanDefinition(beanName))
        {
            String nameToLookup = this.originalBeanName(name);
            if (args != null)
            {
                return parentBeanFactory.getBean(nameToLookup, args);
            }

            return parentBeanFactory.getBean(nameToLookup, requiredType);
        }

        if (!typeCheckOnly)
        {
            this.markBeanAsCreated(beanName);
        }

        try
        {
            //这里根据Bean的名字取得BeanDefinition
            final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
            this.checkMergedBeanDefinition(mbd, beanName, args);
            //获取当前Bean的所有依赖Bean,这样会触发getBean的递归调用,直到取到一个没有任何依赖的Bean为止
            String[] dependsOn = mbd.getDependsOn();
            String[] var11;
            if (dependsOn != null)
            {
                var11 = dependsOn;
                int var12 = dependsOn.length;

                for(int var13 = 0; var13 < var12; ++var13)
                {
                    String dep = var11[var13];
                    if (this.isDependent(beanName, dep))
                    {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }

                    this.registerDependentBean(dep, beanName);
                    this.getBean(dep);
                }
            }
            //这里通过调用createBean方法创建Singleton bean的实例,这里有一个回调函数getObject,会在getSingleton中
            //调用ObjectFactory的createBean
            //下面进入到createBean中进行详细分析
            if (mbd.isSingleton())
            {
                sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>()
                {
                    public Object getObject() throws BeansException
                    {
                        try
                        {
                            return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                        }
                        catch (BeansException var2)
                        {
                            AbstractBeanFactory.this.destroySingleton(beanName);
                            throw var2;
                        }
                    }
                });
                bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            //这里是创建prototype bean的地方
            else if (mbd.isPrototype())
            {
                var11 = null;

                Object prototypeInstance;
                try
                {
                    this.beforePrototypeCreation(beanName);
                    prototypeInstance = this.createBean(beanName, mbd, args);
                }
                finally
                {
                    this.afterPrototypeCreation(beanName);
                }

                bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
            else
            {
                String scopeName = mbd.getScope();
                Scope scope = (Scope)this.scopes.get(scopeName);
                if (scope == null)
                {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }

                try
                {
                    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>()
                    {
                        public Object getObject() throws BeansException
                        {
                            AbstractBeanFactory.this.beforePrototypeCreation(beanName);

                            Object var1;
                            try
                            {
                                var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            }
                            finally
                            {
                                AbstractBeanFactory.this.afterPrototypeCreation(beanName);
                            }

                            return var1;
                        }
                    });
                    bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException var21)
                {
                    throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var21);
                }
            }
        }
        catch (BeansException var23)
        {
            this.cleanupAfterBeanCreationFailure(beanName);
            throw var23;
        }
    }
    //这里对创建对bean进行类型检查,如果没有问题,就返回这个新建的bean,这个bean已经是包含了依赖关系的Bean
    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass()))
    {
        try
        {
            return this.getTypeConverter().convertIfNecessary(bean, requiredType);
        }
        catch (TypeMismatchException var22)
        {
            if (this.logger.isDebugEnabled())
            {
                this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var22);
            }

            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    else
    {
        return bean;
    }
}

getSingleton实现

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}
    
//具体实现
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //在已经注册了的单例map集合(singletonObjects)中获取特定beanName的bean
    Object singletonObject = this.singletonObjects.get(beanName);
    //检查这个bean是不是null,并且这个bean不在正在创建中的bean的map缓存(singletonsCurrentlyInCreation)中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            //从已经缓存了的单利对象集合中获取beanName对应的Bean
            singletonObject = this.earlySingletonObjects.get(beanName);
                //如果不存在,并且允许早期引用当前创建的对象
            if (singletonObject == null && allowEarlyReference) {
                //根据beanName获取在可以在调用时返回单例Object实例)的工厂。
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    //如果返回的工厂不为空就把对应的beanName放到earlySingletonObjects中,并移除singletonFactories中的值
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    //如果获取到的对象是空,就返回null
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下进行的。我们都知道,对于IoC容器的使用,Spring提供了许多的参数配置,每一个参数配置代表了一个IoC容器的实现特性,这些实现特性很多需要在依赖注入的过程中或者对Bean进行生命周期管理中完成,尽管可以用最简单的方式来描述IoC容器,将它看成一个hashMap,但是只能说这个hashMap是容器的最基本的数据结构,而不是IoC容器的全部,SpringIoC容器作为一个产品,其价值体现在一系列相关的产品特性上,这些产品特性以依赖反转模式的实现为核心,为用户更好的使用依赖反转提供便利,从而实现一个完整的IoC容器。

下面的图可以看成是依赖注入的一个大致的过程

重点来说,getBean是依赖注入的起点,之后会调用createBean,下面通过createBean代码来了解这个过程,在这个过程中,Bean对象会根据BeanDefinition定义的要求生成,在AbstractAutowireCapableBeanFactory实现了这个createBean,createBean不但生产了需要的Bean,还对Bean初始化进行了处理,比如实现了BeanDefinition中的init-method属性定义,Bean后置处理器等。
在这里插入图片描述
AbstractAutowireCapableBeanFactory中的createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException 
{
    if (this.logger.isDebugEnabled()) 
    {
        this.logger.debug("Creating instance of bean '" + beanName + "'");
    }

    RootBeanDefinition mbdToUse = mbd;
    Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) 
    {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }
	//这里判断需要创建的Bean是否可以实例化,这个类是否可以通过类装载器载入
    try 
    {
        mbdToUse.prepareMethodOverrides();
    } 
    catch (BeanDefinitionValidationException var7) 
    {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var7);
    }

    Object beanInstance;
    try 
    {
        beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
        if (beanInstance != null) 
        {
            return beanInstance;
        }
    } 
    catch (Throwable var8) 
    {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
    }

    beanInstance = this.doCreateBean(beanName, mbdToUse, args);
    if (this.logger.isDebugEnabled()) 
    {
        this.logger.debug("Finished creating instance of bean '" + beanName + "'");
    }

    return beanInstance;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值