IOC总结

1. IOC概述

三个问题:

  1. IOC是什么

    1. 为什么用它
    2. 怎么用

1.1 是什么?

两个概念:管制反转,依赖注入

来看一下传统的干活形式:在对象繁多职责准则的根底上,一个对象很少有不依赖其余对象而实现本人的工作,所以这个时候就会呈现对象之间的依赖。而体现在咱们的开发中,就是须要什么对象的时候,就创立什么对象,此时对象创立的控制权在咱们本人手里。当对象创立的太多的时候,就会呈现一个对象更改,就得更改所有依赖它的对象,耦合性大。自主性体现的同时也呈现了对象耦合重大的状况

这个时候,咱们就会思考,能不能咱们在用的时候间接拿到这个对象去用,而将创建对象的能力交给第三方,这样咱们就不须要关怀对象是怎么创立的了。行将本人的控制权交出去。这就是管制反转

这个时候,就会有另一个问题产生了,对象怎么能力间接被咱们拿来用呢。对象创立的时候,咱们把这个对象注入到这个对象中,而后就能够应用了。这就是依赖注入

另一个问题,耦合性怎么被解决掉的?通过管制反转咱们仅仅应用了这个对象,如果对象产生了批改,咱们仅仅须要批改第三方创建对象的形式即可,这个时候难道还会呈现所谓的对象耦合吗?

实现这些工作的就是IOC容器,它帮忙咱们创建对象,而后在对象被应用的时候,将对象注入到这个对象中。而因为IOC创建对象是通过反射来创立的,所以其速度不如间接new对象


还不了解???释怀,听笔者讲一个故事,笔者最喜爱讲故事了

前段时间,天气逐步回暖,鉴于家里没有短袖的状况,笔者只能抉择购买了。这个时候笔者有两种抉择,第一、去生产衣服的厂家间接去买(便宜);第二、去实体店或者网店购买(较低廉)。之后,因为笔者属于宅男大军的一员,间接网上购物。

这个场景就是一个典型的管制反转的过程。笔者不须要关注衣服怎么生产的,而是仅仅去淘宝(IOC容器)上,寻找本人想要的衣服(对象),而后间接拿过去用即可。然而因为存在中间商赚差价,所以价格更贵(工夫更长)

最初两句话:

管制反转:将本人的控制权交给本人信赖的第三方,甲乙之间不存在依赖关系

依赖注入:凋谢一个端口留给A,而后在须要的时候,将B注入到A中。

1.2 为什么用

在下面,笔者曾经很清晰的形容了为什么要应用IOC,次要起因就是因为对象之间的耦合。

1.3 怎么用

1.3.1 XML

通过书写XML配置文件,向容器中增加须要注入的Bean

1.3.2 Annotation

通过@Configuration注解指定配置类。

2. IOC架构

一个图搞定,这个就是IOC的架构思路,这不是其执行流程图

咱们接下来一步一步来解读。

2.1 文言版

在第一章中咱们理解了IOC是来帮忙咱们治理和创建对象的。

这个时候咱们须要一个承载咱们须要创立信息的容器,即图中的XML或者注解,那么有了咱们本人的BeanDefiniton信息当前,咱们须要一个接口用来读取这些信息,于是呈现了BeanDefinitionReader用来读取咱们本人的Bean信息。

那么咱们须要思考一个问题了,那么多的对象怎么生产呢?

答案就是工厂模式。Spring默认的工厂是DefaultListableBeanFactory,没错,Spring中的所有对象(容器对象和咱们本人创立的对象)都是由他创立的。大批量生产对象

这个时候又有了一个问题,咱们不想通过BeanFactory间接生产了,须要对这个工厂进行一些特定解决,于是呈现了BeanFactoryPostProcessor,用来对工厂做一些特定的解决。咱们本人能够通过实现这个接口,进行自定义BeanFactory。又有兄弟说了:我想独自创立一些我喜爱的对象,安顿FactoryBean诞生了,它能够帮忙咱们创立一个咱们须要的对象(第四局部具体解释他们之间的区别)。

那又有兄弟说了:我想让对立的对象创立之前依照我的形式进行一些非凡的行为,简略,安顿

BeanPostProcessor呈现了,他提供了两个办法:一个在对象实例化之后初始化之前,执行外部的Before办法,在初始化之后,执行After办法。(Bean生命周期,第四局部详解

这个时候有兄弟有疑难了,不是说BeanPostProcessor在创建对象之前执行吗?怎么是创立结束当前才执行的Before办法。

如果各位兄弟理解过指令重排序这个概念,那么肯定会听过一个案例,创立一个对象须要三步

  • 创立空间(实例化)
  • 初始化
  • 赋值

其中在初始化和赋值会呈现指令重排序

依据这个点,应该能够get到一个点,实例化和初始化不一样。

所以又引出了一个点,咱们对Bean进行一些操作,怎么操作,必定是批改属性,或者增加一些属性等等,须要期待其在堆中开拓空间即实例化实现当前执行吧。

所以BeanPostProcessorbefore办法在实例化之后执行,初始化之前执行。

经验过后面一大堆的操作当前,终于咱们的对象进入咱们兜里了(容器里)。

对于销毁,个别状况下咱们通过ApplicationContext拿不到其销毁办法,只能通过其子类实现获取,对于销毁同样的流程,先执行一个销毁之前的操作,而后再销毁。

2.2 理论工作流程

看过Spring源码或者听过的都晓得外面有一个办法叫做refresh,他实现了好多事件。当然他的行为也代表了整个IOC容器加载和实例化对象的过程。第三章的代码解读中咱们认真看

执行过程:

  • 加载配置文件,初始化零碎环境Environment接口
  • 筹备上下文环境,初始化一些配置资源
  • 创立一个工厂
  • 为工厂增加各种环境
  • 获取子类本人重写的BeanFactoryPostProcessor
  • 执行容器和咱们本人的BeanFactoryPostProcessor
  • 注册BeanPostProcessor
  • 国际化解决
  • 转播器
  • 子类初始化Bean
  • 注册监听器,观察者模式
  • 实现Bean创立
  • 公布相应的事件,监听器

3. IOC源码解读

写在之前:IOC的源码比较复杂,所以集体倡议视频形式学习,大家能够B站搜寻阁主梧桐(笔者认为讲的不错的一个解读),如果大家不喜爱视频的形式,又想深度学习IOC源码那么举荐程序员囧辉它的博客对于IOC的解说十分深刻。另外本文接下来的Spring源码,次要是通过图示的办法梳理其流程,作者程度无限。如有谬误请留言。

3.1 上下文配置启动

在创立ClassPathXmlApplicationContext的时候,构造方法中执行了这些办法。

说白了,加载了一个解析配置文件门路的加载器;而后又通过零碎环境变量拿到这个配置文件,进行一些配置文件的去空格,转换表达式等等操作(没有进行解析);最初就是那个被我标成红色东东,refresh办法中它实现了简直所有的工作。上面细聊

3.2 refresh

这个办法简直实现了所有的操作,创立工厂,执行Processor等等,实例化对象,开启事件监听等等。

接下来细聊

3.3.1 prepareRefresh()

这个办法的次要作用是为利用上下文的刷新做一些筹备性的工作。校验资源文件,设置启动工夫和沉闷状态等。

3.3.2 obtainFreshBeanFactory()

能够get到,它次要就是创立了一个工厂BeanFactory,并且解析了配置文件,加载了Bean定义信息(面试的时候间接答这个点就够了,如果想说的能够将上面的bean信息加载聊聊)

没错,标红的就是咱接下来细聊的点

这个就是加载配置文件的过程,留神:此时依然没有解析,解析在标红的上面

这个就是读取的过程,具体解析流程来自parse中,这个间接调用了Java中的解析XML的类库,有趣味自行翻阅,最初返回了一个Document对象。

通过Document对象,读取外部的标签,执行不同的办法,逻辑和MyBatis中解析配置文件的思维雷同,大家自行翻阅。

此时所有的Bean定义信息都被保留到了BeanDefinitionRegistry接口,而后走子类DefaultListableBeanFactory工厂的注册办法

3.3.3 prepareBeanFactory(beanFactory)

BeanFactory筹备一些环境,不便在实例化的时候应用,同时增加容器本人的BeanPostProcessor

3.3.4 postProcessBeanFactory

留给子类扩大的BeanFactoryPostProcessor

3.3.5 invokeBeanFactoryPostProcessors(beanFactory)

这个类,波及到了两个接口。

  • BeanFactoryPostProcessor
  • BeanDefinitionRegistryPostProcessor接口,这个接口是BeanFactoryPostProcessor的子接口,它的优先级比BeanFactoryPostProcessor更高

它的总体执行流程是:先执行BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor,而后再执行BeanFactoryPostProcessor

下图是BeanDefinitionRegistryPostProcessor接口的处理过程

BeanFactoryPostProcessor的解决逻辑

总逻辑就是先分类,曾经解决过的间接跳过,没有解决过的,分类解决,逻辑和下面的雷同。

3.3.6 registerBeanPostProcessors

这个办法的逻辑和下面的一样,只不过下面是间接执行了BeanFactoryPostProcessor,而这个仅仅注册没执行。

首先拿到工厂中所有的BeanPostProcessor类型的Bean,而后分类解决,排序注册。

3.3.7 initMessageSource()

执行国际化内容

3.3.8 initApplicationEventMulticaster

创立了一个多播器,为增加Listener提供反对。

次要逻辑:

  • 容器中是否存在applicationEventMulticaster,如果存在间接注册
  • 如果不存在,创立一个SimpleApplicationEventMulticaster,注册到容器中。
3.3.9 onRefresh()

子类扩大

3.3.10 registerListeners()

观察者模式的实现

protected void registerListeners() {        // 拿到以后容器中的监听器,注册到多播器中        for (ApplicationListener<?> listener : getApplicationListeners()) {            getApplicationEventMulticaster().addApplicationListener(listener);        }        //拿到容器中为监听器的Bean,注册        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);        for (String listenerBeanName : listenerBeanNames) {            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);        }        // 清空开始的事件,到播送器中        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;        this.earlyApplicationEvents = null;        if (earlyEventsToProcess != null) {            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {                getApplicationEventMulticaster().multicastEvent(earlyEvent);            }        }    }
3.3.11 finishBeanFactoryInitialization
这一部分的内容太多了,所以采纳代码和图解的形式来解说。
    /**     * Finish the initialization of this context's bean factory,     * initializing all remaining singleton beans.       在上下文工厂中实现所有Bean 的初始化     */    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {        // 初始化上下文转换服务Bean        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {            beanFactory.setConversionService(                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));        }                //如果不存在前入值解析器,则注册一个默认的嵌入值解析器,次要是注解属性解析        if (!beanFactory.hasEmbeddedValueResolver()) {            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));        }        // 初始化LoadTimeWeaverAware        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);        for (String weaverAwareName : weaverAwareNames) {            getBean(weaverAwareName);        }        // Stop using the temporary ClassLoader for type matching.        beanFactory.setTempClassLoader(null);        // Allow for caching all bean definition metadata, not expecting further changes.        beanFactory.freezeConfiguration();        // Instantiate all remaining (non-lazy-init) singletons.        //实例化,重点        beanFactory.preInstantiateSingletons();    }

下图是创立Bean的次要流程

依照途中的序号一个一个说:

  1. BeanDefinition是否须要合并。BeanDefinition依据不同类型的配置文件信息,会将Bean封装到不同的Bean信息定义类中。比方咱们罕用的配置文件版的GenericBeanDefinition;注解扫描版的ScannedGenericBeanDefinition等等。

而在这个过程中就呈现了,父定义和子定义,咱们须要在理论解决定义信息的时候进行合并解决,次要有一下三个方面

  • 存在父定义信息,应用父定义信息创立一个RootBeanDefinition,而后将自定义信息作为参数传入。
  • 不存在父定义信息,并且以后BeanDefinitionRootBeanDefintion类型的,间接返回一份RootBeanDefintion的克隆
  • 不存在父定义信息,并且以后BeanDefintion不是RootBeanDefintiton类型的,间接通过该BeanDefintion构建一个RootBeanDefintion返回

下面的流程也是源码中的执行流程

  1. isFactoryBean。判断是否为FactoryBean

简略介绍一下:FactoryBean是让开发者创立本人须要Bean接口。外部提供了三个办法

T getObject() throws Exception;//返回的Bean信息Class<?> getObjectType();//返回的Bean类型default boolean isSingleton() {return true;}//是否单例

当咱们通过GetBean间接该Bean的时候,获取到的是该工厂指定返回的Bean类型。如果想要获取该Bean自身,须要通过一个前缀取得&

@Overridepublic boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {    String beanName = transformedBeanName(name); //解析真正的BeanName    Object beanInstance = getSingleton(beanName, false);//获取容器中的bean    if (beanInstance != null) {//如果容器中存在,间接返回该Bean是否为FactoryBea类型        return (beanInstance instanceof FactoryBean);    }    //没有Bean信息,查看这个Bean信息    if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {            // 从父工厂中获取        return             ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);        }    //MergedBeanDefinition来查看beanName对应的Bean是否为FactoryBean        return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));    }

再来看一个点,这个就是从容器中获取Bean的次要办法,也是解决循环依赖的逻辑

protected Object getSingleton(String beanName, boolean allowEarlyReference) {    //查看以后容器中是否存在该Bean        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) {                    //获取该Bean的ObjectFactory工厂                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);                    //如果以后工厂不为空                    if (singletonFactory != null) {                        //创立一个对象实例,此时处于半初始化状态                        singletonObject = singletonFactory.getObject();                        //增加到晚期援用中                        this.earlySingletonObjects.put(beanName, singletonObject);                        //移除创立晚期援用的工厂,因为该Bean曾经创立且增加到了晚期容器中,不须要再次进行创立了。                        this.singletonFactories.remove(beanName);                    }                }            }        }        return singletonObject;}

来聊一下它是怎么解决循环援用的?

它引入了一个三级缓存的概念

/**寄存了所有的单例Bean */private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);/** 寄存了Bean创立须要的ObejctFactory */private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);/** 寄存了晚期创立的Bean,此时的Bean没有进行属性赋值,仅仅通过构造方法创立了一个实例 */private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);//正在创立的Beanprivate final Set<String> singletonsCurrentlyInCreation =            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

在产生循环援用的时候,它首先通过ObejctFactory工厂将Bean创立进去,此时的对象并没有进行属性赋值,仅仅在堆中开拓了空间。而后将此时的Bean增加到earlySingletonObjects容器里,也就是说这个容器中保留的Bean都是半成品。而在之后的属性赋值中,因为对象为单例的,所以其援用地址不会发生变化,即对象最终是残缺的。

  1. getBean通过这个办法间接创立了所有的对象,这也是Spring最外围的办法了

先来看一下它整体的一个流程

它的次要逻辑是:先拿到以后要实例化的Bean的实在名字,次要是为了解决FactoryBean,拿到当前,从以后容器中看是否曾经创立过该Bean,如果存在间接返回。

如果不存在,获取其父工厂,如果父工厂不为空,而且以后容器中不存在以后Bean的信息,则尝试从父工厂中获取Bean定义信息,进行Bean实例化

如果父工厂为空,将以后Bean信息寄存到alreadyCreated缓存中。

获取以后Bean的合并信息(getMergedLocalBeanDefinition),查看以后Bean是否存在依赖,如果存在则判断以后Bean和依赖Bean是否为循环依赖,如果不是循环依赖则先创立依赖Bean

判断以后Bean的作用域。

如果以后Bean是单例对象,间接创立Bean实例

如果以后Bean是多例对象,将以后Bean信息增加到正在创立多例缓存中,创立结束当前移除

如果以后Bean是其余类型,如Requtst,Session等类型,则自定义一个ObejctFacotry工厂,重写getObject办法,创建对象

对象创立当前,判断以后对象是否为本人须要的对象,如果是间接返回;如果不是进行类型转换,如果类型转换失败,间接抛异样

接下来看一眼CreateBean的执行

这个办法次要实现的事件是:通过Bean的名字拿到对应的Class对象;如果以后Bean获取到的Class对象不为空且该RootDefintiton能够间接获取到该Bean,克隆一份Bean定义信息,不便之后应用。

验证以后Bean上的@Override信息。执行BeanPostProcessor,返回一个代理对象(如果存在代理的话)

如果不存在代理,则间接创立Bean

接下来咱们来聊一下这个玩意——resolveBeforeInstantiation

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {        Object bean = null;        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {            // Make sure bean class is actually resolved at this point.            //以后定义信息不是合并,且存在Bean增强器            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {                //获取Bean的Class类型                Class<?> targetType = determineTargetType(beanName, mbd);                if (targetType != null) {                    //如果不为null,则执行前置处理器                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);                    if (bean != null) {                        //如果前置处理器不为null,则后置处理器执行,跳过spring默认初始化                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);                    }                }            }            //代表曾经再实例化之前进行了解析            mbd.beforeInstantiationResolved = (bean != null);        }        return bean;    }

来吧,持续,看一下那个前置处理器逻辑

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {        for (BeanPostProcessor bp : getBeanPostProcessors()) {            //拿到工厂中的所有的BeanPostProcessor            if (bp instanceof InstantiationAwareBeanPostProcessor) {                //找到所有咱们须要的增强器                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;                // 返回一个代理实例                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);                if (result != null) {                    return result;                }            }        }        return null;    }

后置处理器就不看了,就调用了所有的后置处理器,而后执行了一遍,没有其余逻辑。

接下来持续咱们的正题:doCreateBean

其大抵流程如上图:

先判断当前是否单例,而后从FactoryBean缓存中看一下是否存在正在创立的Bean,如果存在拿出,如果不存在则创立一个以后Bean的包装类实例。而后拿到这个类的实例和实例类型,执行当前后置处理器。

以后Bean是否为单例,是否容许循环依赖,时候正在进行创立,如果是,创立一个以后Bean的ObejctFactory以解决循环依赖的问题

填充Bean的属性,进行Bean的实例化。

查看晚期容器缓存中(缓存中的二级缓存中是否有该Bean)。如果有,则阐明存在循环依赖,则进行解决

先看循环依赖吧

if (earlySingletonExposure) {    //从晚期的Bean容器中拿到实例对象,此时的Bean必然存在循环依赖    Object earlySingletonReference = getSingleton(beanName, false);    if (earlySingletonReference != null) {                if (exposedObject == bean) {            exposedObject = earlySingletonReference;        } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {                        //获取依赖的全副Bean信息            String[] dependentBeans = getDependentBeans(beanName);            Set < String > actualDependentBeans = new LinkedHashSet < > (dependentBeans.length);            for (String dependentBean: dependentBeans) {                //革除这些Bean信息,此时的Bean曾经是脏数据了                if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {                    //无奈清理存入actualDependentBeans中                    actualDependentBeans.add(dependentBean);                }            }            if (!actualDependentBeans.isEmpty()) {                throw new BeanCurrentlyInCreationException            }        }    }}// Register bean as disposable.try {    registerDisposableBeanIfNecessary(beanName, bean, mbd);} catch (BeanDefinitionValidationException ex) {    throw new BeanCreationException(        mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}

接着来,createBeanInstance

Spring提供了三种形式创建对象的包装:

  • 通过供给者对象对象间接创立。obtainFromSupplier
  • 通过工厂办法间接创立。
  • 默认创立。

    • 构造方法是否须要主动注入
    • 构造方法不须要主动注入,调用默认的构造方法

这个办法执行结束当前,你应该通晓的一个点是:此时对象实例曾经创立了,剩下的就是执行一系列增强器和初始化办法,属性填充等等。


咱们依照代码执行程序来,属性填充即populateBean

这个办法执行逻辑:

首先判断传入的Bean是否为null,如果为null则判断Bean定义信息中是否存在属性值,如果存在,异样;如果不存在跳过

以后Bean定义信息是否为合并当前的,如果是且此时的工厂中存在InstantiationAwareBeanPostProcessors,那么在属性填充之前进行批改Bean的信息

拿到所有的属性值,解析属性值的主动注入形式,Type或者Name,进行主动注入

判断是否存在InstantiationAwareBeanPostProcessors,批改之前设置的属性

判断是否存在依赖查看,查看依赖

属性赋值


接下来看执行初始化办法,就是调用BeanPostprocessor,init等办法

这个就是这个办法的执行流程图,置信到这个中央,大家应该对于为什么BeanPostProcessor的before办法会在init办法执行理解了。这个办法的作用仅仅是用来进行一个生命周期的打印,对象在之前曾经创立了。


接下来看一下销毁的办法。registerDisposableBeanIfNecessary

对于单例Bean来说,Spring将须要销毁的Bean寄存到了disposableBeans缓存中,通过DisposableBeanAdapter封装了销毁Bean

对于其余作用域来说,自定义了销毁回调函数,不过最初还是封装为DisposableBeanAdapter

在封装为DisposableBeanAdapter的过程中,会首先判断该Bean中是否存在destroy办法,而后给赋值给destroyMethodName变量。再次判断这个办法的参数,如果参数的个数大于1,则抛出异样

3.3.12 finishRefresh

这个办法进行了一系列的资源清理和

protected void finishRefresh() {        // 清空上下文资源缓存        clearResourceCaches();        // 初始化生命周期处理器        initLifecycleProcessor();        // 将曾经刷新结束的处理器流传(扔到)生命周期处理器中        getLifecycleProcessor().onRefresh();        // 推送上下文刷新结束的工夫到相应的监听器        publishEvent(new ContextRefreshedEvent(this));        // Participate in LiveBeansView MBean, if active.        LiveBeansView.registerApplicationContext(this);    }

initLifecycleProcessor,这个办法极具简略,就看一下以后Bean中是否存在生命周期处理器,如果存在间接应用这个,如果不存在则创立一个默认的,并且注册为一个单例的扔到容器中。

4. 常见题目

4.1 Bean的生命周期?

Spring官网解释在BeanDefinition接口的正文里

答:Bean残缺的生命周期是:

  • 设置一系列Aware接口的性能
  • 实例化Bean
  • 调用BeanPostProcessorbefore办法
  • 执行InitializingBean接口办法afterPropertiesSet
  • 执行init办法
  • 调用BeanPostProcessorpostProcessAfterInitialization办法
  • 调用DestructionAwareBeanPostProcessors接口的postProcessBeforeDestruction办法
  • 调用destory办法

4.2 FactoryBean和BeanFactory的区别

答:BeanFactorySpring默认生产对象的工厂。

FactoryBeanSpring提供的一个生产特定类型和特定对象的工厂。例如Mybatis-spring中的SqlSessionFactoryBean就是通过这种办法创立的。

4.3 什么是循环依赖?Spring如何解决循环依赖的?

答:循环依赖是指:在创立A对象的时候须要注入B对象;在创立B对象的时候须要注入A对象,两者相互依赖。

呈现循环依赖有两种状况:

  • 结构器依赖(无奈解决)
  • 属性注入(能够解决

解决循环依赖,Spring引入了三级缓存的概念。下面的源码解说中介绍过

  • singletonObjects寄存了所有的单例Bean,此时所有的Bean信息都是残缺的
  • earlySingletonObjects寄存了晚期的Bean,此时仅仅创立了一个Bean实例,未进行属性填充
  • singletonFactories寄存了Bean的工厂

Spring通过将创立Bean的工厂裸露进去,而后在呈现循环依赖的时候通过这个工厂常见一个bean,而后将这个Bean注入,因为对象是单例的,所以在接下来的属性填充中,能够保障为同一个对象,至此,循环依赖解除。

应用三太子敖丙的一句话:解决循环依赖的过程就是力扣中的第一题两数之和的过程

4.4 什么是IOC

答:IOC存在两个点:

  • 管制反转。将常见对象的控制权交给第三方,这里的第三方就是Spring
  • 依赖注入。在类中须要应用到的对象,全副通过反射从第三方容器注入而不是本人创立。这里的第三方容器即Spring

4.5 ApplicationContext和BeanFactory的区别

答:

  • ApplicationContext采纳了立刻加载,即加载配置文件的时候就创立了对象。BeanFactory采纳了延时加载的形式,应用的时候才创立。
  • 对于BeanPostProcessorBeanFactoryProcessor而言,BeanFactory是手动注册,ApplicationContext采纳了主动注册。

4.6 Spring 框架中都用到了哪些设计模式?

答:

  • 单例模式。这个不须要多说
  • 代理模式。AOP应用到的
  • 装璜着模式。BeanWrapper
  • 工厂模式。BeanFactory,创建对象的时候
  • 模板办法模式。JDBCTemplate
  • 观察者模式。各种事件监听
  • ……

更多原创文章和Java系列教程请关注公众号@MakerStack