Spring 面试题+答案

Spring是一个开源的J2EE应用框架,管理Bean的生命周期。IOC控制反转,依赖注入用于对象创建。AOP是IOC的扩展,用于日志、事务等场景。Bean的生命周期包括实例化、属性填充、初始化和销毁。事务传播有七种特性,如Required、Requires_new等,处理方法间的事务嵌套。循环依赖通过三级缓存解决。Spring使用多种设计模式,如单例、工厂、模板等。
摘要由CSDN通过智能技术生成

1.什么是Spring

Spring 是一个开源的J2EE应用框架,是针对Bean的生命周期进行管理的轻量级容器。

2.解释一下什么是IOC和AOP

IOC:控制反转。以前一般创建对象是由创建者去通过new创建,有了Spring之后,创建对象全部交给Spring容器去帮我们创建进行管理。
DI:依赖注入。就是将对象的属性注入到具体的对象中。@Autowried,@Resource populateBean方法注入。
容器:存储对象。使用map结构去保存对象,在Spring中存储对象一般有三级缓存,singletonObjects用来存放完整对象。earlySingletonObject 存放半成品对象,singletonFactory用来存放lambda表达式和对象名称映射,整个Bean的生命周期,从创建到使用到销毁,都是由Spring容器来帮我们控制。

(当前,在整个ioc体系中还有很多细节的点,但是我是之前看的,太久了,记不清楚了,Spring中所有的bean都是通过反射创建的,constructor, newInstance,在整个流程 中还包含了很多扩展点,比如比较重要的接口 BeanFactoryPostProcessor, BeanPostProcessor,用来实现扩展功能,aop就是在ioc基础之上的一个实现扩展,是通过BeanPostProcessor实现的,ioc除了创建对象之后还有一个重要的点就是对象填充,生命周期能说多少说多少)
动态代理,概念是面向切面编程。

Aop是IOC的一个扩展功能,先有ioc再有AOP,只是在在IOC整个流程中的一个扩展点而已
讲述的步骤:
总:aop的概念,应用场景(日志、事务、缓存、参数校验、权限验证、安全检查),动态代理技术
分:bean创建过程中有一个步骤可以对bean进行扩展实现,aop本身就是一个扩展功能,所以在BeanPostProcessor的后置处理方法中实现。

  1. 代理对象的创建过程(advice,切面,切点)
  2. 通过jdk或者Cglib的方式来生成代理对象
  3. 在执行方法调用的时候,会调用到生成的字节码文件中,直接找到DynamicAdisoredInterceptor类中的intercept方法。从此方法开始执行。
  4. 根据之前定义好的通知来生成拦截器
  5. 从拦截器中依次获取每一个通知开始进行执行,在执行过程中,为了方便找到下一个通知是哪一个,会有一个CglibMethodsInvocation的对象,找到的时候是从-1的位置开始查找并执行的。

3.简单描述bean的生命周期

去背诵生命周期的流程图。
Spring容器帮助我们去管理对象,从对象的生产到销毁过程都由容器来控制,其中包含初始化和实例化两个关键环节,当然在整个过程中会有一些扩展点的关键点,下面来详细描述下各个环节和步骤:
在这里插入图片描述

  1. 实例化Bean对象,通过反射原理生成,在源码中有一个createBeanInstance的方法是专门用来创建对象的。
  2. 当Bean对象创建完成后,对象属性值都是默认值的,所以要开始给Bean填充属性,通过populateBean方法来完成对象的属性填充,中间会涉及到循环依赖的问题。后面详细说明。
  3. 向Bean对象中设置容器属性,会调用invokeAwareMethods方法来将属性设置到具体的对象中
  4. 调用BeanPostProcessor中前置处理方法来进行Bean对象的扩展工作,ApplicationContextPostProcessor,EnbaddValueResolver等对象。
  5. 调用invokeInitMethods方法来完成初始化的调用,在此方法过程中,需要判断当前对象是否实现了InitalizingBean接口,如果实现了调用afterPropertiesSet方法来最后设置Bean对象。
  6. 调用BeanPostProcessor的后置处理方法,完成Bean对象的后置处理工作,aop就是在此处实现的,实现的接口名字叫做AbstractAutoProxyCreator
  7. 获取到完整对象,通过getBean方法去进行对象的获取和使用。
  8. 当对象使用完成之后,容器在关闭的时候,会销毁对象,首先会判断是否实现了DispoableBean接口,然后去调用destroyMethod方法。
重新理解bean的生命周期

1.首先启动我们的Spring服务,会去扫描加载我们的注解和XML文件,通过loadBeanDefinitions方法去加载到我们的Bean定义信息,放到beanDefinitionMap的集合中。
2.然后通过createBeanInstance方法创建bean对象。通过Java的反射机制拿到类的构造方法,拿取会有一些规则。
3.创建好bean对象后,bean的属性都是默认值,开始对bean属性进行填充,通过populateBean方法进行属性填充,机制是通过三级缓存。
4.开始对bean进行初始化操作,首先是初始化容器属性,通过invokeAwareMethods方法来将容器属性设置到bean对象中
5.调用BeanPostProcessor的前置处理方法。
6.调用InvokeInitMethods方法来完成初始化调用,在此方法中,会判断当前对象是否实现了InitalizingBean接口,如果实现了就调用afterPropertiesSet方法,这个方法是程序员实现的。表示Bean填充属性后执行。
7.调用BeanPostProcessor的后置处理方法,包括AOP的处理器、销毁前的处理器,和系统级的处理器,到这里就完成了bean的创建,bean已经可以用了
8.通过addSigleton方法放入单列池中。
9.通过getBean方法去获取和使用bean对象。
10.在容器close的时候,会对bean对象进行销毁,在执行destroy销毁方法的时候,回去调用我们销毁前后的方法。

4. 谈一下Spring事务传播

传播特性有几种?七种
Required,Requires_new,nested,Support,Not_Support,Never,Mandatory
某一个事务嵌套另一个事务的时候怎么办?
A方法调用B方法,AB方法都有事务,并且传播特性不同,那么A如果有异常,B怎么办?如果B有异常,A怎么办?
总:事务的传播特性是指的是不同方法的嵌套调用过程中,事务应该如何进行处理,是用同一个事物还是不同事物,出现异常时会回滚还是提交,两个方法之间的相互影响,在日常工作中,使用的比较多的就是required,Requires_new,nested
分:
1. 先说事务的不同分类,可以分为三类:支持当前事务,不支持当前事务,嵌套事务。
2. 如果外层方法时required,内层方法是,required,requires_new,nested
3. 如果外层方法时requires_new,内层方法是,required,requires_new,nested
4. 如果外层方法时nested,内层方法是,required,requires_new,nested
名词解释:
Required:Spring的默认事务传播类型,如果当前没有事务就新建一个事务,如果有事务就加入这个事务中。
Requires_New:创建新事物。如果当前有事务,就会挂起。
Support:当前存在事务就加入事务,如果当前没有事务,就以非事务执行。
Not_Supported:以非事务执行,如果有事务就挂起事务。
Never:如果有事务就抛异常。
Nested:嵌套事务,如果当前事务存在就在嵌套事务中执行,否则开启一个新事物。
Mandatory:强制事物,如果当前存在事务则加入,否者抛异常。

5.谈谈你对循环依赖的理解

什么事循环依赖?A依赖B,B依赖A
Spring中Bean对象的创建都要经过初始化和实例化(也叫属性填充)的过程,通过将对象的状态分开,存在成品bean对象和半成品bean对象的方式,来分别进行初始化和实例化,成品和半成品存储的时候需要不同的缓存来存储。

  1. 只有一级缓存行不行?
    不行,会把成品bean对象和半成品bean对象放到一起,而半成品对象无法暴露给外部使用,所以要分开存储,一级缓存存放成品对象,二级缓存存放半成品对象。
  2. 只有二级缓存行不行?
    如果整个应用中不涉及Aop的存在,那么二级缓存足以解决循环依赖的问题,如果Aop中存在了循环依赖,那么必须要使用三级缓存才能解决。
  3. 为什么使用三级缓存?
    三级缓存value值是ObjectFactory,是一个函数式接口,不是直接进行调用,只有在调用的getObject方法的时候才会去调用里面的存储的lambda表达式,存在的意义是保证整个容器在运行的时候同名的bean对象只有一个。

6.Spring中用到了哪些设计模式

单例模式:Spring中Bean都是单例的
工厂模式:BeanFactory
模版方法:postProcessorBeanFactory,onRefresh
观察者模式:;listener,event,multicast
适配器模式:Adapter
装饰者模式:BeanWrapper
责任链模式:使用AOP的时候会有一个责任链模式
代理模式:JDK动态代理
委托者模式:delegate
建造者模式:builder
策略模式:Xml的解析和一些配置文件的解析

7.BeanFactory和FactoryBean的区别

BeanFactory和FactoryBean都可以用来创建Bean对象,只是创建的流程方式不同。
当使用BeanFactory的时候,必须严格遵守Bean的生命周期,经过一系列的繁杂的步骤之后才可以创建单例对象,是流水线式的的创建过程。
而FactoryBean是用户可以自定义Bean的对象的创建流程,不需要按照Bean的生命周期来创建,在此接口中包含了三个方法:
isSingleton: 判断是否是单例对象。
getObjectType:获取对象类型
getObject:在此方法中可以自己创建对象,使用new方式或者代理方式都可以,用户可以根据自己的需要随意的去创建对象,很多框架都继承的时候都会实现BeanFactory接口,比如Feign。

8.ApplicationContext和BeanFactory的区别

1.BeanFactory是访问spring容器的根接口,里面提供了某些基本方法的约束和规范,为了满足更多的需求,2.ApplicationContext实现了此接口,并在此接口的基础之上做了某些扩展功能,提供了更加丰富的api调用,一般我们使用的时候用ApplicationContext更多。
3.Bean的初始化时机不同,原始BeanFactory是在调用getBean方式的时候才进行bean的创建,而AplicationContext是在加载配置文件,初始化容器的时候就将bean初始化和实例化好的。
4.Bean的创建核心流程都在BeanFactory中,而且ApplicationContext内部还维护者BeanFactory的引用,所以ApplicationContext和BeanFactory不仅有继承关系,有有融合关系。

9.谈谈你对循环依赖的理解

什么事循环依赖?A依赖B,B依赖A
Spring中Bean对象的创建都要经过初始化和实例化(也叫属性填充)的过程,通过将对象的状态分开,存在成品bean对象和半成品bean对象的方式,来分别进行初始化和实例化,成品和半成品存储的时候需要不同的缓存来存储。

  1. 只有一级缓存行不行?
    不行,会把成品bean对象和半成品bean对象放到一起,而半成品对象无法暴露给外部使用,所以要分开存储,一级缓存存放成品对象,二级缓存存放半成品对象。
  2. 只有二级缓存行不行?
    如果整个应用中不涉及Aop的存在,那么二级缓存足以解决循环依赖的问题,如果Aop中存在了循环依赖,那么必须要使用三级缓存才能解决。
  3. 为什么使用三级缓存?
    三级缓存value值是ObjectFactory,是一个函数式接口,不是直接进行调用,只有在调用的getObject方法的时候才会去调用里面的存储的lambda表达式,存在的意义是保证整个容器在运行的时候同名的bean对象只有一个。

10.Spring常用的注解

@Bean、@Configuration、@ComponentScan、@Value、@Import、@Autowired、@Resource

11.Spring事务失效的场景

1.没有抛出异常或者没有指定注解接收的异常
2.同一类中方法发生调用
3.方法不是public的,或者方法使用了final static修饰
4.使用了错误的传播机制
5.没有被Spring管理
6.方法没有被spring容器管理也会事务失效(面试中曾考过)

12.@Autowird和@Resource的区别

1.来源不同:Autowird来自spring,Resource来之JDK
2.装配方式不同:Autowird优先按照类型,Resource优先按照名称
3.Autowird注入必须容器要存在bean,否则报错,除非使用required=false(表示没有就跳过)。
4.属性不同:Autowird是required,Resource是name和type
5.作用范围不同
6.Autowird注入的时候,如果要注入的对象有多个实现类需要指定name属性,可以修改实例名或者加qualifier注解。

13.AOP失效的场景

1.被final、static、private修饰的方法或构造方法。
2.调用和被调用的方法在同一个类
3.引入公共模块时,如果包路径不同则也会失效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值