1. 为什么要使用 spring?
- spring 提供 ioc 技术,容器会帮你管理依赖的对象,从而不需要自己创建和管理依赖对象了,更轻松的实现了程序的解耦。
- spring 提供了面向切片编程,这样可以更方便的处理某一类的问题,比如日志输出,事务控制,异常的处理等。。
- spring 提供了事务支持,使得事务操作变的更加方便。
- 更方便的框架集成,spring 可以很方便的集成其他框架,比如 MyBatis、hibernate 等。
2. 解释一下什么是 aop?
aop 是面向切面编程,通过预AOP:面向切面编程。(Aspect-Oriented Programming)
AOP利用代理模式,AOP可以说是对OOP的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合,实现AOP的技术。
我来解释一下:这个面向切面编程
我们的一个类,它里面的方法我们都可以增强,(什么是增强?就是CRUD),我们就可以把这些方法称之为连接点(Joinpoint),但是我们在实际开发中,可能不需要把所有的方法都增强,可能增强方法中的某一个或者某几个,那么真正被增强的方法我们就可以称之为切入点(Pointcut),那么我们切入了以后要做哪些事呢?比如说:要在方法删除之后写出日志的记录,那么这些日志的记录我们就可以称之为通知(Advice),被增强的这个对象(类)就称之目标(Target),把通知应用到目标上的这个过程就是织入(Weaving),然后织入了增强以后,我们就会产生一个代理对象
主要分为两大类:
一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码,属于静态代理
编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
简单来说就是统一处理某一“切面”(类)的问题的编程思想,比如统一处理日志、异常等。
3. 解释一下什么是 ioc?
ioc:Inversionof Control(中文:控制反转)是 spring 的核心,IOC:控制反转也叫依赖注入,IOC利用java反射机制,对于 spring 框架来说,就是由 spring 来负责控制对象的生命周期和对象间的关系。
所谓控制反转是指,本来被调用者的实例是有调用者来创建的,这样的缺点是耦合性太强,
IOC则是统一交给spring来管理创建,将对象交给容器管理,你只需要在spring配置文件中配置相应的bean,以及设置相关的属性,让spring容器来生成类的实例对象以及管理对象。
在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的时候,就把它已经初始化好的那些bean分配给你需要调用这些bean的类。 更轻松的实现了程序的解耦。
4. spring 常用的注入方式有哪些?
一.目前使用最广泛的 @Autowired:自动装配
基于@Autowired的自动装配,默认是根据类型注入,可以用于构造器、接口、方法注入,使用方式如下:
@Autowired
构造方法、方法、接口
@Autowired默认是根据参数类型进行自动装配,且必须有一个Bean候选者注入默认required=true,如果允许出现0个Bean候选者需要设置属性“required=false”,“required”属性含义和@Required一样,只是@Required只适用于基于XML配置的setter注入方式,只能打在setting方法上。
1)、构造器注入:通过将@Autowired注解放在构造器上来完成构造器注入,默认构造器参数通过类型自动装配,如下所示:
public class Test1 {
private MessageInterface message;
@Autowired //构造器注入
private Test1(MessageInterface message) {
this.message = message;
//省略getter和setter
}
}
(2)、接口注入:通过将@Autowired注解放在接口实例上来完成接口注入。
public class Test2 {
@Autowired //接口注入
private MessageInterface messageInterface;
//省略getter和setter
}
(3)、方法参数注入:通过将@Autowired注解放在方法上来完成方法参数注入。
public class Test3 {
private MessageInterface message;
@Autowired //setter方法注入
public void setMessage(MessageInterface message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
public class Test4 {
private MessageInterface message; //
private List<String> list;
@Autowired(required = true) //任意一个或多个参数方法注入
private void initMessage(MessageInterface message, ArrayList<String> list) {
this.message = message;
this.list = list;
}
//省略getter和setter
}
二[email protected]注解可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。如果没有指定name属性,并且按照默认的名称找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。
比如:我们用@Autowired为上面的代码MessageInterface接口的实例对象进行注解,它会到Spring容器中去寻找与MessageInterface对象相匹配的类型,如果找到该类型则将该类型注入到messageInterface字段中;
如果用@Resource进行依赖注入,它先会根据指定的name属性去Spring容器中寻找与该名称匹配的类型,例如:@Resource(name="messageInterface"),如果没有找到该名称,则会按照类型去寻找,找到之后,会对字段messageInterface
5.spring bean生命周期
Spring上下文中的Bean也类似,【Spring上下文的生命周期】
- 1. 实例化一个Bean,也就是我们通常说的new
- 2. 按照Spring上下文对实例化的Bean进行配置,也就是IOC注入
- 3. 如果这个Bean实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的是Spring配置文件中Bean的ID
- 4. 如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(),传递的是Spring工厂本身(可以用这个方法获取到其他Bean)
- 5. 如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文,该方式同样可以实现步骤4,但比4更好,以为ApplicationContext是BeanFactory的子接口,有更多的实现方法
- 6. 如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用After方法,也可用于内存或缓存技术
- 7. 如果这个Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法
- 8. 如果这个Bean关联了BeanPostProcessor接口,将会调用postAfterInitialization(Object obj, String s)方法
- 注意:以上工作完成以后就可以用这个Bean了,那这个Bean是一个single的,所以一般情况下我们调用同一个ID的Bean会是在内容地址相同的实例
- 9. 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean接口,会调用其实现的destroy方法
- 10. 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法
- 以上10步骤可以作为面试或者笔试的模板,另外我们这里描述的是应用Spring上下文Bean的生命周期,如果应用Spring的工厂也就是BeanFactory的话去掉第5步就Ok了
6. spring 有哪些主要模块?
- spring core:框架的最基础部分,提供 ioc 和依赖注入特性。
- spring context:构建于 core 封装包基础上的 context 封装包,提供了一种框架式的对象访问方法。
- spring dao:Data Access Object 提供了JDBC的抽象层。
- spring aop:提供了面向切面的编程实现,让你可以自定义拦截器、切点等。
- spring Web:提供了针对 Web 开发的集成特性,例如文件上传,利用 servlet listeners 进行 ioc 容器初始化和针对 Web 的 ApplicationContext。
- spring Web mvc:spring 中的 mvc 封装包提供了 Web 应用的 Model-View-Controller(MVC)的实现。
7. spring 中的 bean 是线程安全的吗?
spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。
实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”(原型),这样请求 bean 相当于 new Bean()了,所以就可以保证线程安全了。
有状态就是有数据存储功能。
无状态就是不会保存数据。
8. spring 支持几种 bean 的作用域?
spring 支持 5 种作用域,如下:
singleton:spring ioc 容器中只存在一个 bean 实例,bean 以单例模式存在,是系统默认值;
prototype:每次从容器调用 bean 时都会创建一个新的示例,既每次 getBean()相当于执行 new Bean()操作;
Web 环境下的作用域:
request:每次 http 请求都会创建一个 bean;
session:同一个 http session 共享一个 bean 实例;
global-session:用于 portlet 容器,因为每个 portlet 有单独的 session,globalsession 提供一个全局性的 http session。
注意: 使用 prototype 作用域需要慎重的思考,因为频繁创建和销毁 bean 会带来很大的性能开销。
9. spring 事务实现方式有哪些?
- 声明式事务:声明式事务也有两种实现方式,基于 xml 配置文件的方式和注解方式(在类上添加 @Transaction 注解)。
- 编码方式:提供编码的形式管理和维护事务。
10. 说一下 spring 的事务隔离?
spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT(使用数据库的设置),其他四个隔离级别和数据库的隔离级别一致:
ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;
ISOLATIONREADUNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读);
ISOLATIONREADCOMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读),SQL server 的默认级别;
ISOLATIONREPEATABLEREAD:可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读),MySQL 的默认级别;
ISOLATION_SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。
脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。
不可重复读 :是指在一个事务内,多次读同一数据。
幻读 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。
11. 说一下 spring mvc 运行流程?
- spring mvc 先将请求发送给 DispatcherServlet。
- DispatcherServlet 查询一个或多个 HandlerMapping,找到处理请求的 Controller。
- DispatcherServlet 再把请求提交到对应的 Controller。
- Controller 进行业务逻辑处理后,会返回一个ModelAndView。
- Dispathcher 查询一个或多个 ViewResolver 视图解析器,找到 ModelAndView 对象指定的视图对象。
- 视图对象负责渲染返回给客户端。
12. 说一下 spring mvc 运行流程(详细版)?
- (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响应用户。
13. spring mvc 有哪些组件?
- 前置控制器 DispatcherServlet。
- 映射控制器 HandlerMapping。
- 处理器 Controller。
- 模型和视图 ModelAndView。
- 视图解析器 ViewResolver。
14.Springmvc的优点:
(1)可以支持各种视图技术,而不仅仅局限于JSP;
(2)与Spring框架集成(如IoC容器、AOP等);
(3)清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。
(4) 支持各种请求资源的映射策略。
15.SpringMVC怎么样设定重定向和转发的?
(1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4"
(2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"
16.SpringMVC常用的注解有哪些?
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。