Spring基础知识

◇◆丶佛笑我妖孽 提交于 2020-08-11 01:47:28

Q:Spring依赖注入方式都有哪几种?

A:Spring依赖注入方式有3种,分别是属性注入(set注入)、构造方法注入。工厂方法注入。可以通过注解或者XML配置文件的形式进行注入。

1、属性注入

属性注入即通过 setXxx() 方法注入 Bean 的属性值或者依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际项目中最常采用的注入方式 。

属性注入要求 Bean 提供一个默认的构造函数,并为需要注入的属性提供对应的 Setter 方法 。Spring 先调用 Bean 的默认构造函数实例化 Bean 对象,然后通过反射来调用 Setter 方法注入属性值。

2、构造方法注入

构造函数注入保证一些必要的属性在 Bean 实例化时就得到设置,这样 Bean 在实例化后就可以使用 。
 
使用构造函数注入的前提是 Bean 必须提供带参的构造函数。 如果构造函数进行了重载,则需要通过指定索引、参数类型等方式,定位唯一的构造函数。 否则Spring将 随机采用一个匹配的构造函数来实例化 Bean ,而被选择的构造函数可能并不是我们所希望的,导致出现不可预期的结果。 
 
3、工厂方法注入
 
为需要注入的Bean指定它的Factory Bean,并指定Factory Method,然后通过Factory Method提供的方法获取要注入的对象实例。
 

也可以直接指定Bean的Factory Method,然后通过静态方法调用。

详情可以参考简书文章:https://www.jianshu.com/p/d41c596316c1

 

Q:Spring自动装配的方式都有哪几种?

A:

1、no  : 默认的方式是不进行自动装配,通过手工设置ref 属性来进行装配bean

<bean id="person" class="com.myapp.core.autowire.Person">
    <property name="book" ref="book" />
</bean>
<bean  id="book" class="com.myapp.core.autowire.Book"></bean

2、byName:通过在Bean中设置autowire=“byName”,Spring自动寻找与property中的name相同的Bean进行装配。

<bean id="person" class="com.myapp.core.autowire.Person" autowire="byName">
</bean>
<bean  id="book" class="com.myapp.core.autowire.Book"></bean>

3、byType:通过在Bean中设置autowire="byType",Spring自动寻找与property中的数据类型一致的Bean进行装配。

<bean id="person" class="com.myapp.core.autowire.Person"  autowire="byType"/>
<bean  id="book" class="com.myapp.core.autowire.Book"></bean>

4、constructor:通过在Bean中设置autowrite="constructor",Spring自动寻找与构造函数的数据类型一致的Bean进行装配。

<bean id="person" class="com.myapp.core.autowire.Person"  autowire="constructor"/>
<bean  id="book" class="com.myapp.core.autowire.Book"></bean>

5、auto-detect:先尝试使用constructor装配,使用constructor装配失败则使用byType进行自动装配。

<bean id="person" class="com.myapp.core.autowire.Person"   autowire="autodetect" />
<bean  id="book" class="com.myapp.core.autowire.Book"></bean>

详情可以参考知乎文章: https://www.zhihu.com/question/39361250/answer/80937680

 

Q:什么是循环依赖,Spring怎么解决循环依赖问题

A:

并非所有循环依赖Spring都能够解决。Spring不能解决构造器的循环依赖、以及Prototype类型属性的循环依赖。Spring能够解决Singleton类型属性的循环依赖,而Spring的Bean,默认就是Singleton(单例)类型。

Spring解决单例类型属性的循环依赖,是通过三级缓存以及提前暴露早期对象引用的技术。

Spring的三级缓存通过Map实现,如下:

源码 级别 描述
singletonObjects 一级缓存 用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
earlySingletonObjects 二级缓存 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
singletonFactories 三级缓存 存放 bean 工厂对象,用于解决循环依赖

现在假设A、B两个类的属性互相依赖,如下:

class A{

      private  B  b;

}

class  B{

      private A  a;

}

Spring创建对象时会调用doCreateBean()方法,在该方法中,Spring会先进行实例化(为对象分配内存空间),再通过populateBean()方法,进行属性赋值。

当创建A类的a对象时,Spring会先对a对象进行实例化,此时a对象在堆中已经实例化完成,只是相关的属性还没有赋值而已。(可以理解为一个半成品对象)然后Spring发现a对象依赖了b属性,它会将a对象先放入三级缓存中,再递归的调用doCreateBean(),尝试创建b对象。在创建b对象的过程中,会去缓存中一级一级的查找,在三级缓存中,b找到了a对象的引用,此时b对象会顺利的完成实例化和初始化过程,b对象的实例会被放入一级缓存中。然后重新返回到a对象的属性赋值过程,此时因为b对象已经完全创建好了,a对象也会顺利的完成初始化,a对象的早期暴露引用会从三级缓存中删除,a对象的实例会被放入一级缓存中。这样就解决了循环依赖的问题。

详情可以参考:  https://www.jianshu.com/p/8bb67ca11831 

                            https://www.jianshu.com/p/a77e64250a9e

 

Q:简述Spring Bean的生命周期

A:

主要逻辑都在doCreateBean()方法中,从大的阶段来记忆,分为4个阶段,③和④是用户可以自定义扩展的阶段。这4个阶段是依次执行的:

①实例化( createBeanInstance() )

②属性注入( populateBean()  )

③初始化( initializeBean() )

④销毁( disposableBean() )

Spring为我们提供了很多常用的扩展点,以下根据扩展点的类型对扩展点进行分类:

①影响多个Bean的接口

  • BeanPostProcessor
  • InstantiationAwareBeanPostProcessor

Spring最核心的2个接口,Spring的IOC、AOP等也有之相关。其中InstantiationAwareBeanPostProcessor继承自BeanPostProcessor,作用于实例化前后。BeanPostProcessor作用于初始化前后。分别对应第①和第③阶段生命周期。InstantiationAwareBeanPostProcessor有2个调用点,postProcessBeforeInstantiation在doCreateBean()之前进行, postProcessAfterInstantiation 在populateBean()属性赋值方法内进行,但先于实际的属性赋值。

BeanPostProcessor的调用点包括 postProcessBeforeInitialization 和 postProcessAfterInitialization,这2个方法包围住了invokeInitMethods()。

②只调用一次的接口

Aware接口:都是在初始化前调用,作用是从Spring容器中获取一些容器资源,可以具体分为2组:

    1、BeanNameAware,BeanClassLoaderAware,BeanFactoryAware

    这一组Aware都是在代码中直接调用的(invokeAwareMethods())。

    2、EnvironmentAware, EmbeddedValueResolverAware , ApplicationContextAware

    这一组Aware均为 ApplicationContext 相关,是通过BeanPostProcessor提供的postProcessBeforeInitialization()来实现的。

最后是2个生命周期接口:

InitializingBean  ,对应初始化阶段,在invokeInitMethods()方法中调用,可自定义init-method。

DisposableBean  ,对应销毁阶段,在 ConfigurableApplicationContext的close()方法中执行,本质是获取所有实现了DisposableBean的Bean,并调用它们的destroy()方法,可自定义destroy-method。

详情可参考:

https://www.jianshu.com/p/1dec08d290c1

https://www.jianshu.com/p/38032b0b9869

 

Q:Springboot启动流程

A:

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!