Spring 面经

1.说说什么是IOC?

  • IOC作为Spring的核心技术模块,其主要是讲对象的实例过程交由容器进行管理,而无需我们开发者去处理对应的实例。
  • 通过反射创建对象,由容器管理对象生命周期和依赖关系。
  • 当然在里面不同Bean之间存在着DI,其实现原理就是通过反射,动态的向对象在注入自己所需要的对象

2.说一下AOP是什么?

  • 将一些常用的逻辑进行封装,使开发者专注于业务逻辑,更容易解耦。

  • 封装的逻辑一般有拦截器、校验器、日志、全局异常处理等

  • 切面(定义方法),切点(定义注解),连接点(定义程序进入切面的点)

  • 通知:前置before,后置after,环绕around

  • 动态代理分两个,一个是jdk代理,一个是cglib代码,两个代理的区别如下:

    • jdk代码是基于接口 的,但凡该接口实现了的方法被使用,都会调用对应的切面逻辑,适合日志统一、权限检测等情况。使用Java的反射机制,动态生成一个实现了指定接口的代理类。内存占用低。
    • cglib代码需要精确在具体的类,能够更加细腻的决定哪些类在使用时被代理。通过字节码技术,在运行时生成一个目标类的子类。内存占用高且性能开销大。

3.说一下Beanfactory 和 FactoryBean的区别是什么?

通过Bean Factory进行统一管理Bean的获取,通过FactoryBean你可以控制对象如何创建,而ObjectFactory借助Scope接口自定义scope你可以控制对象的创建时机

  • BeanFactory:

    • 一个工厂类接口
    • 负责管理和创建 Bean 的基本容器
    • BeanFactory–>SpringIoC容器顶级接口,定义了对单个bean的获取,对bean的作用域判断,获取bean类型,获取bean别名的功能
      • ListableBeanFactory–>扩展了BeanFactory接口,并提供了对bean的枚举能力
      • HierarchicalBeanFactory–>扩展了BeanFactory接口,并提供了访问父容器的能力
      • AutowireCapableBeanFactory–>扩展了BeanFactory接口,并提供了自动装配能力
      • ConfigurableBeanFactory–>扩展了HierarchicalBeanFactory,并提供了对容器的配置能力
      • ConfigurableListableBeanFactory–>扩展了ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory接口,并提供了忽略依赖,自动装配判断,冻结bean的定义,枚举所有bean名称的功能
  • FactoryBean

    • 一个实现了FactoryBean<T>接口的Bean
    • 允许自定义 Bean 的创建逻辑,返回任意类型的对象,例如可以在创建过程中添加一些逻辑(如记录日志、处理异常等)。
    • 当从 BeanFactory 获取这个 Bean 时,实际上得到的是 FactoryBeangetObject() 方法返回的对象,而不是 FactoryBean 本身
  • ObjectFactory:

    • 主要用于延迟对象的创建,创建时机由 Scope 接口控制,可以根据需要在不同的上下文中创建对象
    • 适合用于场景中需要动态获取 Bean 的情况
    • 在依赖注入时,可以通过调用 objectFactory.getObject() 来创建目标对象。
    • 在创建代理对象时,ObjectFactory 允许在 Bean 还未完全初始化时提前暴露对象。这使得在 AOP 场景中,能够注入代理对象而不是原始对象,确保切面逻辑能够生效

4.说一下Bean的生命周期?

大致就是我程序启动后,通过 loadBeanDefinitions 扫描所有xml配置、注解将Bean记录在beanDefinitionMap中,通过 createBean 遍历 beanDefinitionMap 创建bean,然后就是容器通过 createBeanInstance 进行对象构造,然后进行属性填充,当然属性填充的前后是有一些 XXawarepostprocessor方法对bean进行预处理,然后就是初始化,初始化前后也有对应的后置处理器,然后就是如果有实现InitializingBean接口,那么可以通过afterPropertiesSet方法进行属性自定义填充,最后就是销毁,当然在销毁之前也是有对应的接口方法执行

Bean的生命周期 ——五步骤

  1. 实例化
  2. 依赖注入
  3. 初始化
  4. 使用Bean
  5. 销毁Bean

Bean的生命周期 ——七步骤

  1. 实例化
  2. 依赖注入
  3. 初始化前 BeanPostProcessor before方法
  4. 初始化
  5. 初始化后 BeanPostProcessor after方法
  6. 使用Bean
  7. 销毁Bean

Bean的生命周期 ——十步骤

  1. 实例化
  2. 依赖注入
  3. BeanNameAware BeanFactoryAware接口方法执行
  4. 初始化前 BeanPostProcessor before方法
  5. InitialingBean接口方法执行
  6. 初始化
  7. 初始化后 BeanPostProcessor after方法
  8. 使用Bean
  9. DisposableBean接口方法执行
  10. 销毁Bean

Bean的生命周期——完整的步骤

  1. loadBeanDefinitions —— 扫描所有xml配置、注解将Bean记录在beanDefinitionMap中
  2. 加载定义 BeanDefinition #createBean ——遍历 beanDefinitionMap 创建bean
  3. InstantiationAwareBeanPostProcessor #postProcessBeforelnstantiation——主要来获取Bean实例,如果找不到就执行接下来操作,找到就跳过下面的操作;
  4. AutowiredAnnotationBeanPostProcessor #determineCandidateConstructors——决定选择哪一个构造器
  5. 实例化 ——对Bean进行构造器实例化
  6. InstantiationAwareBeanPostProcessor #postProcessAfterlnstantiation——在 Bean 实例化后进行检查和处理
  7. InstantiationAwareBeanPostProcessor #postProcesslnstantiation——在依赖注入开始前进行额外的配置
  8. 依赖注入(属性赋值)——为Bean内部所需的属性进行赋值
  9. BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 接口方法执行——通过 invokeAwareMethods 方法允许 Bean 获取其名称、BeanFactory 和类加载器的引用
  10. 初始化前 BeanPostProcessor before方法——在 Bean 初始化之前执行,允许进行一些准备工作或修改 Bean
  11. 初始化—— invokeInitMethods调用
  12. InitialingBean接口方法执行——Bean 实现了 InitializingBean 接口,调用其 afterPropertiesSet() 方法进行自定义初始化
  13. 初始化后 BeanPostProcessor after方法——在 Bean 初始化后执行,允许进行后处理操作,包含着AOP的操作
  14. 使用Bean
    • Scope为 singleton的就返回Bean给用户,并存入缓存池;
    • prototype bean返回给用户,剩下生命周期用户控制
  15. DisposableBean接口方法执行
  16. 销毁Bean

Bean级生命周期方法: Bean 类直接实现接口的方法,这些方法只对当前 Bean 生效。

  • BeanNameAwareBeanFactoryAwareApplicationContextAwareInitializingBeanDisposableBean

Aware 类型的接口:能够拿到 Spring 容器中的一些资源,Aware 之前的名字就是可以拿到什么资源,所有的 Aware 方法都是在初始化阶段之前调用的


5.@Resource 和 @Autowire 的区别是什么?

装配方式不一样

  • @Resource注解读取先从对象的名称去查找,查找不到就根据其类型去查找;
    • 位于javax.annotation里面的jar包
  • @Autowire默认根据类型去查找,如果类型有多个实现的话,就根据名称去查找
    • 通过@Qyalifier注解去规定调用哪一个Bean
    • 位于spring框架下bean的jar包

6.@Componse和@Bean的区别是什么?

  • 两者都能被容器识别作为Bean,不过两者的用法不一样,@Bean的灵活性更高;
  • @Componse注解书写在类上面,在程序启动后可以被IOC容器识别并纳入容器内部
  • @Benn注解书写在对象上,并且需要在含有@Configure注解的类里面书写,这个Configure注解相当于配置文件xml的功能,然后里面的@bena注解书写可以灵活的的放回,特别是面对第三方的jar包时,我们要灵活使用里面的Bean对象,那么就可以使用该@Bean注解

7.什么是反射?

反射是一种在运行时动态访问类的信息、方法和字段的机制。特别是在DI中,反射允许程序在运行时加载和使用已经存在的字节码文件,可以动态调用类的方法和访问字段,而不需要在编译时确定具体的类和方法。

8.什么是事务?Spring事务和MySQL的事务之间有什么区别?

  • 事务是指一组操作的集合,这些操作要么全部成功,要么全部失败。事务的主要特性可以用 A(Atomicity)C(Consistency)I(Isolation)D(Durability) 原则来描述;

  • Spring的事务允许通过注解或xml进行控制且Spring的事务具备传播性(REQUIREDREQUIRES_NEWNESTED),允许方法定义事务的边界,允许复杂的业务逻辑,如果当前的没事务就new一个,如果有则加入事务;

  • Mysql事务由数据库引擎管理,直接在数据库层控制,直接处理 SQL 语句的执行、提交和回滚。

  • Spring 的事务回滚会同时触发数据库的回滚,确保所有操作的一致性。SQL 语句自身不具备回滚能力,而是依赖事务控制

9.如果出现循环依赖怎么解决?

  • 加@lazy注解
  • 如果a依赖b,b依赖c,c依赖a,将中间的b换一种方式去实例
  • 把依赖方法直接写入
  • 使用中间体,避免直接依赖

10.说一下SpringMvc的执行流程和调用过程。

DispatcherServlet 是 Spring MVC 的核心,负责请求的接收、处理、分发和响应,是实现 MVC 模式的关键组件
执行过程:

1、用户发送请求到前端控制器DispatcherServlet
2、DispatcherServlet收到请求调用处理映射器HandlerMapping
3、处理映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包含处理器对象和处理器拦截器)返回给DispatcherServlet
4、DispatcherServlet根据处理器Handler获取对应的适配器
5、HandlerAdapter调用处理器Handler
6、Handler(Controller)执行完成后返回ModelAndView
7、HandlerAdapter返回ModelAndView
8、DispatcherServlet统一将返回的ModelAndView派送到ViewResolve(视图解析器)解析
9,视图解析器解析之后返回View
10、对View进行渲染
11、响应用户

调用过程:

DispatcherServlet默认使用WebApplicationContext作为上下文,因此我们来看一下该上下文中有哪些特殊的Bean:
(1)控制层:
1、Controller:处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;
2、HandlerMapping:请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;
3、HandlerAdapter:HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,并且掉处理器的handleRequest方法进行功能处理;
(2)视图层:
4、ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;
5、LocalResover:本地化解析,因为Spring支持国际化,因此LocalResover解析客户端的Locale信息从而方便进行国际化;
6、ThemeResovler:主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;
7、MultipartResolver:文件上传解析,用于支持文件上传;
8、HandlerExceptionResolver:处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);
9、RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;
(3)其他:
10、FlashMapManager:用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景,用于短期数据传递。

11.Spring Boot容器的理解,其加载过程是什么样子的。

SpringBoot容器基于loc进行管理Bean生命周期和依赖关系
执行过程如下:

  • 调用main方法中的run方法
  • 创建springApplication实例
  • 根据程序的配置,准备上下文
  • 加载配置文件
  • 自动配置
  • *创建Bean
  • *依赖注入
  • *初始化
  • *上下文刷新等待请求(确保所有Bean准备就绪)
  • 事件发布,通知应用准备就绪
  • 运行应用

12.tomcat是怎么加载进入容器里面的?

执行过程如下:

  • 调用main方法中的run方法
  • 创建springApplication实例
  • 根据程序的配置,准备上下文
  • 加载配置文件
  • 自动配置
  • *创建Tomcat实例 并配置其端口路径等信息
  • *注册servlet 和 filter(请求预处理、权限控制)
  • *通过webapplication初始化容器
  • *上下文刷新确保所有bean准备就绪
  • 事件发布,通知应用准备就绪
  • tomcat接受请求转发给spring的dispatchservlet,然后分到给不同的hander进行处理
  • hander处理结束返回给tomcat再返回给客户端

13.Spring的一、二、三级缓存是什么?

三级缓存主要是解决循环依赖问题。

  • 一级存储完整的bean;
  • 二级存储未完全实例化的暴露的Bean;
  • 三级存储对应Bean的ObjectFactory;

循环依赖场景:

  • 设 A 依赖 B,B 依赖 A。
  • 当创建 A 时,发现 B 尚未完成,于是将 A 的工厂放入三级缓存。
  • 创建 B 时,同样发现 A 尚未完成,B 的工厂也放入三级缓存。
    处理过程:
  • A 在创建过程中进入三级缓存,随后尝试填充属性,发现需要 B。
  • 创建 B 时,发现 A 的工厂在三级缓存中,便将 A 放入二级缓存。
  • B 完成初始化后,放入一级缓存。
  • A 通过一级缓存获取到 B 的完整实例,完成自身初始化。

14.Applicationcontext与Beanfactory的区别是什么?

  • BeanFactory是Spring底层最基本的接口,这个容器用来管理Bean的加载,实例化,控制生命周期等功能,其Beanfactroy采用延迟注入Bean,只有在bena被使用的时候才会进行注入,优点是不用一次性加载,缺点如果最后调用错误才抛出异常,没办法知道程序潜在的问题
  • ApplicationContext 是 BeanFactory的子类,其特点是当容器被加载时,一次性加载所有的Bean,这样可以发现程序潜在的问题,但是随着而来的就是内存占用较大。

15.Spring Bean的作用域有哪些?

五大作用域:

  • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  • prototype : 每次请求都会创建一个新的 bean 实例。
  • request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
  • session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
  • global-session: 全局 session 作用域,仅仅在基于 Portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值