banner
NEWS LETTER

Spring面试题

Scroll down

1、如何理解Spring IOC和AOP?他们之间的联系?Spring IOC在整个Spring框架中起了什么样的作用? Spring的代理有哪些?实现思想?

Spring IOC:

IOC控制反转是一种思想,将对象的创建交给Spring框架管理。
原理:工厂模式+反射
解决了什么问题:
不需要管对象之间的关系,对象的创建交给容器来管理,松耦合。简化应用的开发,将对象从复杂的依赖关系中解放出来。
ioc和di(依赖注入)的区别:吗
首先 IOC 是一种思想,而 DI 是一种具体的技术实现手段。
IOC 是站着对象的角度上对象的实例化以及管理从程序员的手里交给了 IOC 容器
DI 是站着容器的角度的上会把对象的依赖的其他对象注入到容器中,上述案例中的 A 类依赖 B 类 IOC 容器不仅仅将 A 类放到容器中还需要将其依赖的 B 类也一并加载到 IOC 容器中。

Spring AOP:

AOP是面向切面编程,它将业务逻辑的各个部分进行隔离,使开发人员在编写业务时专注核心业务,从而提高开发效率。

Spring IOC在整个框架中起到了什么作用:
IOC将对象之间相互依赖的关系交给IOC容器管理,并由IOC容器完成对象的注入。这样可以很大程度上简化应用的开发,将应用从复杂的依赖关系中解放出来。
Spring代理有哪些:
JDK Proxy动态代理和Cglib。当被代理的对象实现了某个接口,Spring Aop就会使用JDK Proxy创建代理对象。 对于没有实现接口的对象,就使用Cglib生成一个被代理对象的子类作为代理。

CGLIB动态代理创建的对象比JDK性能高10倍,但CGLIB创建代理对象的时间比JDK高8倍,spring单例模式由于无需频繁创建对象,较适合CGLIb,反之JDK

2.Spring的bean

Spring bean代指被IOC管理的对象。
可以通过xml配置。相关标签
将一个对象声明为Spring Bean的注解:
@Controller
@Service
@Repository
@Component
@Bean

2.1@Bean与@Component

1)@Component作用于类,@Bean作用域对象,通常与@Configuration配合使用
2)如果第三方类的库要注入到Spring IOC中只能通过@Bean

3.MVC分层的原因

MVC是一个设计规范,分层的原因是解耦合,提高代码复用性。
Spring MVC把想项目主要分为Service(处理业务),Dao(数据库操作),Entity(实体类),Controller(控制层,返回数据给前台页面)。

4.spring是如何解决循环注入的问题

从spring的ioc容器获取bean本质是调用getBean()方法,getBean()方法又调用doGetBean()方法,doGetBean()方法先转换对应的beanName,然后去缓存中或者实例方法中去找是否有对应的实例,这里调用的是getSingleton(beanName)方法,getSingleton的传参是beanName,它的流程先去singleObjects这个Map缓存中查看beanName有没有创建好的实例,如果没有则去earlysingObjects这个map中查看beanName有没有对应的实例,singleObjects与earlysingObjects不同的是它存储的是正在创建还没创建完的bean,如果还没有的话就去看singletonFactories缓存中有没有beanName对应的实例工厂,有的话就通过这个实例工厂创建bean,如果getSingleton(beanName)返回的是null的话就会进行bean的实例化,实例化的过程中会调用addSingletonFactory给这个beanName创建一个单例工厂添加到singleFactories缓存中,并且进行属性注入,假如这个属性是引用类型的话,会调用GetBean方法。假如有两个类型的bean,A和B,相互依赖,假如先创建A那么调用getSingleton会返回null,然后实例化的过程会创建一个实例工厂添加到这个缓存中,属性注入时会创建B,B先调用getSingleton(String) 返回的也是null,然会后去实例化,属性注入还会实例化A,然后A又调用getSingleton(beanName)方法,这时还会发现缓存中有实例工厂就会通过实例工厂获取A,这样就终止了循环。

简单版本:

通过提前暴露bean解决(提前曝光就是把这个ObjectFactory放到三级缓存中去)
1)检查A是否在缓存中,不在就进行实例化
2)通过构造函数创建beanA,并通过ObjectFactory曝光beanA
3)进行属性注入,这个时候发现依赖了B,开始实例化B
4)先检查B是否在缓存中,不在就进行实例化
5)通过构造函数创建beanB,并通过ObjectFactory曝光beanB
6)进行属性注入,这个时候发现依赖了A,开始实例化A
7)检查A是否在缓存中,发现其在缓存中,通过ObjectFactory获取beanA
8)B继续剩下的流程直到创建完毕,然后返回到A的执行流程,直到A执行完毕

4.1 Spring能解决构造函数循环依赖?

不行,对于构造函数产生的循环依赖,Spring会抛出异常。假如A和B,先创建A因为构造器注入时,A还未完成实例化,未放进缓存中,就去创建B,B还未实例化,未注入到缓存中有去创建A,所以陷入了死循环,这是无法解决的。

5、bean的生命周期

(1)Bean实例化(Instantiation):实例化一个 Bean 对象
(2) Bean属性赋值:查找被@Autowired和@Value标注的方法或属性,注入需要的值,为 Bean 设置相关属性和依赖
(3)Bean初始化(Initialization):已经生成bean,进行属性赋值

(4)Bean销毁:在容器关闭的时候就会走bean的销毁流程

5.1 依赖注入过程

Spring是通过BeanFactory/ApplicatonContext调用getBean()方法,来获取bean实例的
1)先调用beanName的转换方法transformedBean(name),该方法的作用是根据传入的参数获取真正的beanName。
2)尝试从缓存中加载Bean的单实例,通过从上一步获取的beanName调用getSingleton(beanName)方法从缓存中获取单例,这时的缓存是初始状态,未实例化的。(从缓存中的加载流程是从一级缓存,二级缓存,三级缓存依次获取,三级缓存是用来防止依赖注入的)
3)如果缓存没有就,Bean的实例化,然后进行属性注入
4)Bean的初始化
5)根据不同的scope创建Bean,调用doCreateBean()创建
6)类型转化,当doGetBean方法中的requireType参数不为空时,根据需要进行类型转换

6.Spring AOP如何实现的

本质是通过动态代理实现的 ,主要有以下几个步骤
1)获取增强器,例如被@Aspect注解修饰的类
2)在每创建一个bean时,会检查是否有增强器应用于这个bean,如果有则将增强器作为拦截器参数,使用动态代理创建bean的代理对象。
3)当我们调用被增强过的bean时就会走到代理类中,从而触发增强器,本质和拦截器类似

7、Spring三级缓存

  • 一级缓存 用来保存实例化,初始化都完成的bean
  • 二级缓存 用来保存实例化完成,初始化未完成的对象
  • 三级缓存 用来保存一个对象工厂,提供一个匿名内部类,用于创建二级缓存对象

7.1 解决循环依赖为什么必须要用三级缓存,二级不行吗?

在有AOP的情形下,一开始会往二级缓存放一个普通的对象,生成代理对象后会覆盖二级缓存的对象,在多线程中可能有不一致的风险。

8.过滤器和拦截器的区别

1)实现原理不一样
过滤器是基于函数回调,拦截器是基于java反射机制(动态代理)。Filter中的回调机制是通过doFilter方法中的FilterChain,这个参数实质是一个回调接口。
2)使用范围不一样
过滤器是通过实现的Filter接口,这个接口是javax.servlet包下的,所以它依赖于Tomcat,而拦截器是Spring一个组件。过滤器会拦截前端所有
3)触发时机不同
过滤器是在请求进入Servlet之前处理的,拦截器是在请求进入servlet后,在进入controller前处理的
4)拦截的范围不同
过滤器会对几乎所有的请求进行拦截,而拦截器只会拦截特定的请求
5) bean的注入情况不同
由于过滤器不是由Spring管理的,因此想要自动注入属性需要先把过滤器注入到IOC中去

9.拦截器与AOP的区别

1)拦截器只能针对URL拦截,主要作用于Controller层,但是AOP针对于更具体的代码,一般是Service层
2)拦截器和AOP均是通过代理模式实现

10.Spring MVC的核心组成

  • 前端控制器(DispatcherServlet):主要用于接收客户端发送的Http请求,响应结果给客户端
  • 处理器映射器(HandlerMapping):根据请求的URL定位到对应的处理器(Handler)
  • 处理器适配器(HandlerAdapter):在编写处理器(Handler)要按照适配器的规则去写,通过适配器可以正确的执行Handler
  • 处理器(Handler):就是我们经常写的Controller代码
  • 视图解析器(ViewResolver):进行视图解析,将ModelView对象解析为View返回给视图解析器
  • 视图(View):View是一个接口,例如JSP

10.1Spring MVC的执行流程

1)首先,用户发送HTTP请求给Spring MVC的前端控制器DispatcherServlet
2)DispatcherServlet收到请求后调用HanderMapping处理映射器,跟据请求URL去定位到具体的处理器Handler,并将该处理器返回给DispacherServlet。
3)前端控制器(DispacherServlet)调用处理器适配器,通过处理器适配器调用Handler处理器请求,并向前端控制器返回一个ModelAndView对象
4)前端控制器(DispacherServlet)将ModelAndView对象交给视图解析器去处理,并返回视图View给前端控制器
5)DispacherServlet将视图进行渲染(将模型数据填充进视图中)
6)DispacherServlet将页面响应给用户

11.@Resource和@Autowire

1)@Resource和@Autowire都可以用来装配bean
2)@Autowire默认按照类型装配,默认要求对象必须存在,如果需要允许为null值,可以设置它的required属性为false
3)@Resource如果指定了name或者type则按照指定的进行装配;没有则按照名称进行装配,当找不到匹配的对象时则按照类型进行装配
4)@Autowrie与@Qualifier配合使用

12.Springboot与Spring的区别

Springboot是依赖Spring的,比起Spring,除了拥有Spring的全部功能外,Springboot无需繁琐的xml配置;并且自身已嵌入Tomcat容器,集成了SpringMVC。总的来说Springboot是一个启动Spring的工具,并且简化了Spring配置

13.bean的作用范围

1)singleton:单例模式
2)prototype:原型模式
3)request:每次Http请求会创建一个新的·Bean,请求完后Bean失效并垃圾回收
4)session:和request类似,确保每个session中都有一个Bean实例,session过期后bean失效

14.@RequestMapping与@PostMapping、@GetMapping的区别

@GetMapping和@PostMapping分别处理Http的get方法请求和Http的post请求,它们本质是@RequestMapping的method属性为GET和POST

其他文章
cover
给自己的服务器装个监控!
  • 22/11/16
  • 20:37
  • 小白教程
cover
JVM面试题
  • 22/11/16
  • 13:02
  • java资料