Spring面试题

Spring面试题,第1张

1、说说Spring里用了哪些设计模式?

单例模式:Spring 中的 Bean 默认情况下都是单例的。

工厂模式:工厂模式主要是通过 BeanFactory 和 ApplicationContext 来生产 Bean 对象。

代理模式:最常见的 AOP 的实现方式就是通过代理来实现,Spring主要是使用 JDK 动态代理和 CGLIB 代理。

观察者模式:spring的事件驱动模型使用的是 观察者模式 ,Spring中Observer模式常用的地方是listener的实现。

事件机制的实现需要三个部分,事件源,事件,事件监听器 

事件(ApplicationEvent):负责对应相应监听器事件源发生某事件是特定事件监听器被触发的原因。

监听器(ApplicationListener):对应于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生后的响应逻辑。

事件发布器(ApplicationEventMulticaster): 对应于观察者模式中的被观察者/主题,负责通知观察者对外提供发布事件和增删事件监听器的接口,维护事件和事件监听器之间的映射关系,并在事件发生时负责通知相关监听器

模板方法模式:主要是一些对数据库 *** 作的类用到,比如 JdbcTemplate、JpaTemplate,因为查询数据库的建立连接、执行查询、关闭连接几个过程,非常适用于模板方法。

2:BeanFactory和FactoryBean区别

BeanFactory是bean的工厂,BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如XmlBeanFactory、ApplicationContext等,都是附加了某种功能的实现。

FactoryBean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。

3:BeanFactory和ApplicationContext区别 

  • Bean 工厂(com.springframework.beans.factory.BeanFactory)是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
  • 应用上下文(com.springframework.context.ApplicationContext)建立在BeanFactory 基础之上。

4:说说SpreingBean的生命周期
  1. 实例化,创建一个Bean对象

  2. 填充属性,为属性赋值

  3. 初始化

    • 如果实现了xxxAware接口,通过不同类型的Aware接口拿到Spring容器的资源

    • 如果实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzationpostProcessAfterInitialization方法

    • 如果配置了init-method方法,则会执行init-method配置的方法

  4. 销毁

    • 容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy方法

    • 如果配置了destroy-method方法,则会执行destroy-method配置的方法

5.Spring如何解决循环依赖

何为循环依赖:即2个或以上bean 互相持有对方,最终形成闭环。

本质上解决循环依赖的问题就是三级缓存,通过三级缓存提前拿到未初始化的对象。

第一级缓存:用来保存实例化、初始化都完成的对象

第二级缓存:用来保存实例化完成,但是未初始化完成的对象

第三级缓存:用来保存一个对象工厂,提供 一个匿名内部类,用于创建二级缓存中的对象

A对象的创建过程:

  1. 创建对象A,注入属性时,发现依赖B,转而去实例化B

  2. 同样创建对象B,注入属性时发现依赖A,从一级到三级缓存查询A,从三级缓存通过对象工厂拿到A,把A放入二级缓存,同时删除三级缓存中的A,此时,B已经实例化并且初始化完成,把B放入一级缓存。

  1. 接着继续创建A,顺利从一级缓存拿到实例化且初始化完成的B对象,A对象创建也完成,删除二级缓存中的A,同时把A放入一级缓存

  2. 最后,一级缓存中保存着实例化、初始化都完成的A、B对象

因此,由于把实例化和初始化的流程分开了,所以如果都是用构造器的话,就没法分离这个 *** 作,所以都是构造器的话就无法解决循环依赖的问题了。

6:为什么要三级缓存,二级缓存不可以吗?

不可以,主要是为了生成代理对象。

使用三级缓存主要是为了保证不管什么时候使用的都是一个对象。

只要两个缓存确实可以做到解决循环依赖的问题,但是有一个前提这个bean没被AOP进行切面代理,如果这个bean被AOP进行了切面代理,那么只使用两个缓存是无法解决问题
果加上AOP,两级缓存是无法解决的,不可能每次执行singleFactory.getObject()方法都给我产生一个新的代理对象,所以还要借助另外一个缓存来保存产生的代理对象

七:Spring的通知类型有哪些  pring切面可以应用5种类型的通知: 1. 前置通知(Before):在目标方法被调用之前调用通知功能; 2. 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法 的输出是什么; 3. 返回通知(After-returning ):在目标方法成功执行之后调用通知; 4. 异常通知(After-throwing):在目标方法抛出异常后调用通知; 5. 环绕通知(Around):把前置通知和后置通知都写到一个通知中,组成了环绕通知 PS: 前置通知中,会先把前置方法压入栈底,然后执行完前置方法,释放,再到目标方法。。以此类推 环绕通知中,前置方法执行完后不会被释放,而是要等目标方法与后置方法,最后释放后置方法。。。以此类推 八:连接点(Joint Point)和切入点(Point cut)是什么?

1.连接点(Join point):连接点是在应用执行过程中能够插入切面(Aspect)的一个点。这些点可以是调用方法时、甚至修改一个字段时。

2.切点(Pointcut):切点是指通知(Advice)所要织入(Weaving)的具体位置。

理解:

连接点:连接点是一个虚拟的概念,可以理解为所有满足切点扫描条件的所有的时机。

具体举个例子:比如开车经过一条高速公路,这条高速公路上有很多个出口(连接点),但是我们不会每个出口都会出去,只会选择我们需要的那个出口(切点)开出去。

简单可以理解为,每个出口都是连接点,但是我们使用的那个出口才是切点。每个应用有多个位置适合织入通知,这些位置都是连接点。但是只有我们选择的那个具体的位置才是切点。

九:什么是织入(weaving)?

Spring AOP 框架仅支持有限的几个 AspectJ 切入点的类型,它允许将切面运用到在 IoC 容器中声明的 bean 上。如果你想使用额外的切入点类型或者将切面应用到在 Spring IoC 容器外部创建的类,那么你必须在你的 Spring 程序中使用 AspectJ 框架,并且使用它的织入特性。

十:什么是SpringIOC容器,其作用是什么

SpringIOC即是把对象的控制权交给Spring容器,Spring容器负责创建对象,管理对象(依赖注入DI)装配对象,配置对象,并且负责管理对象的生命周期

作用:

(1)减低代码的耦合度,让容器去维护具体的对象

(2)管理对象的创建和依赖关系的维护

十一:什么是依赖注入

通过DI(Dependency Injection,依赖注入)来实现---> 动态的向某个对象提供它所需要的其他对象。

依赖注入过程中,如果类A中有类B,然后类B的访问权限是private,那么我们在XML里面就需要通过内部类的方式来获取类B,而不能单纯通过set方法获得


    
    
        
         
    
十二:依赖注入的三种方法

(1)构造方法注入---->有参构造函数



        

(2)Set方法---->无参构造函数+set方法



        

(3)注解@Autowired

 
  • no - 这是默认设置,表示没有自动装配。应使用显式 bean 引用进行装配。

  • byName - 它根据 bean 的名称注入对象依赖项。它匹配并装配其属性与 XML 文件中由相同名称定义的 bean。

  • byType - 它根据类型注入对象依赖项。如果属性的类型与 XML 文件中的一个 bean 名称匹配,则匹配并装配属性。

  • 构造函数 - 它通过调用类的构造函数来注入依赖项。它有大量的参数。

  • autodetect - 首先容器尝试通过构造函数使用 autowire 装配,如果不能,则尝试通过 byType 自动装配

十三:Spring框架中的单例bean是线程安全的吗

不是,Spring框架中的单例bean不是线程安全的。

spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线 程的封装处理。

实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来 说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那 就要开发者自己去保证线程安全了,

最简单的就是改变 bean 的作用域, 把“ singleton”变更为“prototype”,这样请求 bean 相当于 new Bean() 了,所以就可以保证线程安全了。

有状态就是有数据存储功能。 无状态就是不会保存数据

十四:Spring如何处理线程并发问题? 在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中, 绝大部分Bean都可 以声明为singleton作用域,因为Spring对一些Bean中非线 程安全状态采用ThreadLocal进行处理, 解决线程安全问题 ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对 数据的访问冲突。 因为每一个线程都拥有自己的变量副本,从而也就没有必要对 该变量进行同步了。ThreadLocal提 供了线程安全的共享对象,在编写多线程代 码时,可以把不安全的变量封装进ThreadLocal -------------------------

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/729369.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存