version:1.0
Spring
Spring基础 / IoC
🙎♂️面试官:举例Spring的模块?
🙋♂答:
Spring是一套为了简化企业级开发的开源框架,主要思想是Spring IoC 和Spring AOP。
spring-core:Spring框架基本的核心组件,包含很多关键类。
spring-beans:提供对bean的创建、解析等功能的支持。
spring-aspects :该模块为 AspectJ 的集成提供支持。
spring-aop :提供对面向切面的编程的支持。
spring-webmvc : 提供对 Spring MVC 的实现。
🙎♂️面试官:Spring、SpringMVC、Spring Boot关系?
🙋♂答:
Spring MVC是Spring中的一个重要模块,可以帮助我们快速构建MVC架构的Web应用。
Spring Boot可以简化可以简化spring应用的创建及部署。它提供了丰富的Spring模块化支持,可以帮助开发者更轻松快捷地构建出企业级应用。
但是在需要构建MVC架构的程序时,还是需要使用Spring MVC作为MVC框架。
🙎♂️面试官:说说对SpringIoC的了解?
🙋♂答:
IoC是控制反转。我们直接使用注解,就可以将对象装配到IoC容器中,那么很多问题都交给了IoC容器来处理,不需要我们去关心对象的创建问题、依赖问题。这样就很大程度上简化了程序的开发。
🙎♂️面试官:什么是Spring Bean?
🙋♂答:
Spring Bean就是IoC容器所要管理的对象。通过注解的方式,我们可以告诉IoC容器管理什么对象。
Spring装配对象的四个注解:
-
@Component(组件):装配普通组件到IOC中。
-
@Repository(仓库):装配持久化层到IOC中。
-
@Service(业务):装配业务逻辑层到IOC中。
-
@Controller(控制):装配控制层/表示层组件到IOC中。
🙎♂️面试官:Bean的作用域?
🙋♂答:
Bean的作用域定义了Bean的生命周期和可见性。我们可以使用@Scope注解管理Bean的作用域。Bean有四个常用的作用域:
singleton
【默认值】:是对单例设计模式的应用,随着IoC容器的创建而创建,随着容器的销毁而销毁。在这过程中,只会创建一个Bean对象。prototype
:每次请求创建一个对象,每次通过容器获取Bean时,都会返回一个新的对象。在使用Prototype作用域时,Spring不会对Bean的生命周期进行管理,需要手动处理Bean的销毁。request
:在一个HTTP请求中,Spring容器创建一个Bean对象;请求关闭,Bean也会被销毁。session
:在同一个HTTP会话中,即使存在多次请求,Spring容器也只会创建一个Bean对象;关闭浏览器,Bean实例被销毁。
因为cookie丢失,由于session是由cookie来维护的,所以会话信息也会丢失。
🙎♂️面试官:Bean的生命周期?
🙋♂答:
- 实例化:Spring容器根据Bean的定义来进行实例化。可以通过构造函数实例化或通过工厂方法创建实例。
- 属性赋值:Spring会通过依赖注入的方法为Bean注入初始值。
- 初始化:调用Bean的初始化回调方法。可以使用
@PostConstruct
注解标注自定义的初始化方法。 - 使用:Bean已经被实例化,可以使用。
- 销毁:可以使用
@PreDestroy
注解标注自定义的销毁方法。
🙎♂️面试官:单例Bean的线程安全问题了解吗?
🙋♂答:
大部分的Bean都是没有实例变量的,比如Dao、Service。但是如果在Bean中定义成员变量,在多线程操作Bean时就可能出现线程安全问题。可以用以下解决方案:
- 避免定义成员变量。
- 使用ThreadLocal,ThreadLoacl是线程隔离的,每个线程都有自己的副本,可以防止多线程操作共享变量带来的问题。
项目中的HostHolder用到了ThreadLocal。
🙎♂️面试官:@Component 和 @Bean 注解的区别是什么?
🙋♂答:
-
作用的位置不同。@Component注解作用于类,@Bean注解作用于方法。
-
装配对象到IoC容器的方式不同。
- @Component通过组件扫描来自动检测和装配到Spring容器中。
- @Bean注解标识的方法Spring只会调用一次,用来产生一个Bean对象。随后Spring将会将这个Bean对象放在自己的IOC容器中。
-
在使用第三方类库中的类要装配到Spring容器时,只能使用@Bean注解。
- 比如项目中用来操作Redis数据库的RedisTemplate就是使用@Bean注解注入的。
🙎♂️面试官:项目中是怎么实现依赖注入的?
🙋♂答:
使用Spring的注解@Autowire实现依赖注入,比如我们的项目中,Controller层依赖于Service层,Service层依赖于Dao层。那么我们就可以使用@Autowire实现依赖注入,将对应的Bean对象注入到我们的属性中,之后直接使用这个属性即可。这样我们就可以实现层与层之间的解耦,减少对象之间的依赖关系。
🙎♂️面试官:@Autowired 和 @Resource 的区别是什么?
🙋♂答:
- 两者的依赖注入方式不同。
- @Autowired默认注入方式为
byType
,根据类型进行匹配。但是如果一个接口存在多个实现类,就会使用byName
进行匹配,名称通常就是类名首字母小写。建议在使用时通过@Qualifier
来显式指定要匹配的类名,而不适用变量名。 - @Resource默认注入方式为
byName
。如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为byType
。 可以通过name
属性来显式指定名称。
- @Autowired默认注入方式为
Spring AOP
🙎♂️面试官:说说自己对于AOP的了解?
🙋♂答:
Spring AOP 可以对某一个方法进行横向的拓展,能够将与业务无关的代码逻辑封装起来,有利于未来的可拓展性和可维护性。比如日志管理,统一异常处理都运用了AOP的思想。
举例:
项目中的统一记录日志,先将所有的Service下的方法都作为切入点。使用@Before注解,在进入切入点之前进行通知,也就是对方法进行了横向的扩展。这样就在每个service类中的方法调用前,都记录了日志。
🙎♂️面试官:Spring AOP 和 AspectJ AOP 有什么区别?
🙋♂答:
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
AspectJ是生态最完整的AOP框架,并且功能相比Spring AOP 很强大。
🙎♂️面试官:AspectJ 定义的通知类型有哪些?
🙋♂答:
Before(前置通知):目标对象的方法调用之前触发
After (后置通知):目标对象的方法调用之后触发
AfterReturning(返回通知):目标对象的方法调用完成,在返回结果值之后触发
AfterThrowing(异常通知) :目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
Around (环绕通知):编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法
Spring MVC
🙎♂️面试官:说说自己对于Spring MVC的了解?
🙋♂答:
使用Spring MVC 与Spring框架集成,可以进行更加简单的Web层开发。其核心思想是通过将业务逻辑、数据进行分离来组织代码。
Spring MVC 下我们一般把后端项目分为 Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。
MVC : Model(模型层)-View(视图层)- Controller(控制层) ,指的是一种设计模式。
🙎♂️面试官:Spring MVC 的核心组件?
🙋♂答:
DispatcherServlet
:核心的中央处理器,负责接收请求、分发,并给予客户端响应。
HandlerMapping
:处理器映射器,根据 uri 去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler
一起封装。
HandlerAdapter
:处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler;
Handler(Controller)
:请求处理器,处理实际请求的处理器。
ViewResolver
:视图解析器,根据 Handler 返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给 DispatcherServlet 响应客户端。
🙎♂️面试官:Spring MVC 的工作流程?
🙋♂答:
- 该请求到达DispatcherServlet,它是Spring MVC框架的核心控制器。
- DispatcherServlet通过调用HandlerMapping 解析器来根据url来确定请求交给哪个处理器处理。找到处理器后,将请求和相应的上下文信息封装为HandlerExecutionChain 对象。
- HandlerExecutionChain:请求处理器的执行链对象。Controller + Interceptor
- DispatcherServlet调用 HandlerAdapter ,会根据 HandlerExecutionChain ,适配执行对应的 Hanlder;
- Controller (处理器)完成对用户请求的处理后,会返回一个ModelAndView对象给DispatcherServlet。
- 这个对象中包含数据模型以及对应的视图信息。数据模型表示控制器向视图传递的数据,视图信息表示用于呈现响应的视图的名称或路径。
- ViewResolver(视图解析器)会根据逻辑上的View(逻辑视图) 查找到实际的View(物理视图)。
- DispatcherServlet会把返回的Model传给View进行视图渲染。
- 最后把View返回给浏览器。
如果需要,Spring 还会应用拦截器和过滤器来处理请求。拦截器可以在请求到达处理器之前或之后执行一些操作,过滤器可以在请求到达 DispatcherServlet
之前或之后执行一些操作。
比如:使用SpringSecurity Filter,过滤器可以在请求到达DispatcherServlet之前执行一些操作。可以进行一个权限的校验。
完。