1.什么是Spring框架
Spring 是一款开源的轻量级 Java 开发框架,旨在提高开发人员的开发效率以及系统的可维护性。
我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发,比如说 Spring 支持 IoC(Inversion of Control:控制反转) 和 AOP(Aspect-Oriented Programming:面向切面编程)、可以很方便地对数据库进行访问、可以很方便地集成第三方组件(电子邮件,任务,调度,缓存等等)、对单元测试支持比较好、支持 RESTful Java 应用程序的开发。
2.Spring框架包含哪些模块
3.什么是IoC
IoC(Inversion of Control:控制反转) 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。不过, IoC 并非 Spring 特有,在其他语言中也有应用。
为什么叫控制反转?
- 控制:指的是对象创建(实例化、管理)的权力
- 反转:控制权交给外部环境(Spring 框架、IoC 容器)
在 Spring 中, IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。
4.什么是AOP
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理
5.Spring AOP 和AspectJ AOP 的区别
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,
如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。
6.Springmvc的核心组件
DispatcherServlet
:核心的中央处理器,负责接收请求、分发,并给予客户端响应。HandlerMapping
:处理器映射器,根据 URL 去匹配查找能处理的Handler
,并会将请求涉及到的拦截器和Handler
一起封装。HandlerAdapter
:处理器适配器,根据HandlerMapping
找到的Handler
,适配执行对应的Handler
;Handler
:请求处理器,处理实际请求的处理器。ViewResolver
:视图解析器,根据Handler
返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给DispatcherServlet
响应客户端
7.Spring 中的依赖注入(DI)是什么,它的作用是什么?它有哪些常用的注入方式?
依赖注入(Dependency Injection,DI)是Spring框架的核心功能之一。它是一种设计模式,目的是为了减少组件之间的耦合度。通过DI,组件的依赖项不是由组件本身创建,而是由外部容器(在Spring中通常指的是Spring容器)在运行时注入。这样做的优点是可以提高组件的可测试性、可维护性和可扩展性。
作用
1. 松耦合
松耦合是DI的主要优点。组件不需要知道依赖的具体实现,只需要知道依赖的接口。这意味着,如果一个组件的依赖改变了实现方式,只要新的实现满足了接口的要求,该组件无需做任何修改。
2. 易于测试
DI使得在单元测试时可以轻松地替换组件使用的实际依赖为mock对象。
3. 易于维护
由于组件间的耦合度降低,系统的各个部分可以独立地发展,不会对其他部分产生影响,这使得维护和更新变得更简单。
4. 易于扩展
DI容器通常支持配置文件或注解,使得替换组件或添加新的依赖成为可能,这在不修改已有代码的情况下实现扩展。
常用的注入方式
在Spring中,有几种常见的依赖注入方式:
1. 构造器注入
通过类的构造器来注入依赖,这是推荐的注入方式,因为它可以保证所需的依赖不会是null,并且依赖项可以是不可变的。
@Component
public class MyService {
private final Dependency dependency;
@Autowired
public MyService(Dependency dependency) {
this.dependency = dependency;
}
}
2. Setter注入
通过类的setter方法注入依赖,这种方式使得你的对象在构造后仍然可以改变其依赖。
@Component
public class MyService {
private Dependency dependency;
@Autowired
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
}
3. 字段注入
直接在字段上注入依赖,虽然它简单方便,但通常不推荐使用,因为这种方式破坏了封装性,使得依赖项在类外部可被修改,并且这种方式不利于单元测试。
@Component
public class MyService {
@Autowired
private Dependency dependency;
}
4. 方法注入
这种方式较少使用,但在某些情况下可能会用到,比如当你需要在某个方法执行时才决定如何注入依赖。
@Component
public class MyService {
private Dependency dependency;
@Autowired
public void prepare(Dependency dependency) {
this.dependency = dependency;
}
}
8.Spring事务的实现方式
编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用
beginTransaction()、 commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
基于 TransactionProxyFactoryBean 的声明式事务管理
基于@Transactional 的声明式事务管理
基于 Aspectj AOP 配置事务
9.SpringMVC的执行流程
(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。