1.为什么要使用 spring?
- 轻量:非入侵性的、所依赖的东西少、资源占用少、部署简单,不同功能选择不同的 jar 组合;
- 容器:工厂模式实现对 JavaBean 进行管理,通过控制反转(IOC)将应用程序的配置和依赖性与应用代码分开;
- 松耦合:通过 xml 配置或注解即可完成 bean 的依赖注入
- AOP:通过 xml 配置 或注解即可加入面向切面编程的能力,完成切面功能,如:日志,事务...的统一处理
- 方便集成:通过配置和简单的对象注入即可集成其他框架,如 Mybatis、Hibernate、Shiro...
- 丰富的功能:JDBC 层抽象、事务管理、MVC、Java Mail、任务调度、JMX、JMS、JNDI、EJB、动态语言、远程访问、Web Service...
2.解释一下什么是 aop?
-
什么是aop?
1.AOP是Spring提供的关键特性之一。AOP即面向切面编程,是OOP编程的有效补充。
2.使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统。
3.从而避免了在业务逻辑的代码中混入很多的系统相关的逻辑——比如权限管理,事物管理,日志记录等等。
4.这些系统性的编程工作都可以独立编码实现,然后通过AOP技术切入进系统即可。从而达到了 将不同的关注点分离出来的效果。 -
AOP相关的概念
1.Aspect :切面,切入系统的一个切面。比如事务管理是一个切面,权限管理也是一个切面;
2.Join point :连接点,也就是可以进行横向切入的位置;
3.Advice :通知,切面在某个连接点执行的操作(分为: Before advice , After returning advice , After throwing advice , After (finally) advice , Around advice );
4.Pointcut :切点,符合切点表达式的连接点,也就是真正被切入的地方; -
AOP 的实现原理
1.AOP分为静态AOP和动态AOP。
2.静态AOP是指AspectJ实现的AOP,他是将切面代码直接编译到Java类文件中。
3.动态AOP是指将切面代码进行动态织入实现的AOP。
4.Spring的AOP为动态AOP,实现的技术为: JDK提供的动态代理技术 和 CGLIB(动态字节码增强技术) 。尽管实现技术不一样,但都是基于代理模式 ,都是生成一个代理对象 。 -
JDK动态代理
1.主要使用到 InvocationHandler 接口和 **Proxy.newProxyInstance() **方法。
2.JDK动态代理要求被代理实现一个接口,只有接口中的方法才能够被代理 。
3.在实现该接口时,可以在 被代理对象调用它的方法时,在调用的前后插入一些代码。
4.而 Proxy.newProxyInstance() 能够利用中间对象来生产代理对象。
5.插入的代码就是切面代码。所以使用JDK动态代理可以实现AOP。 -
CGLIB (code generate library)
1.字节码生成技术实现AOP,其实就是继承被代理对象,然后Override需要被代理的方法,在覆盖该方法时,自然是可以插入我们自己的代码的。
2.因为需要Override被代理对象的方法,所以自然CGLIB技术实现AOP时,就 必须要求需要被代理的方法不能是final方法,因为final方法不能被子类覆盖 。
3.使用到MethodInterceptor接口
3.解释一下什么是 ioc?
1.ioc:Inversion of Control(中文:控制反转)是 spring 的核心,对于 spring 框架来说,就是由 spring 来负责控制对象的生命周期和对象间的关系。简单来说,控制指的是当前对象对内部成员的控制权;
2.控制反转指的是,这种控制权不由当前对象管理了,由其他(类,第三方容器)来管理。
3.“控制反转”,不是什么技术,而是一种设计思想。
4.什么是DI? 与ioc的关系?
- DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。
- 理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
1.谁依赖于谁:当然是应用程序依赖于IoC容器;
2.为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
3.谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
4.注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。 - 关系:IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
5.spring 常用的注入方式有哪些?
Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:
- 构造方法注入
- setter注入
- 基于注解的注入
6. Spring 构造方法注入or属性注入
- 属性注入( Setter-based Dependency Injection)
1.基于setter的DI是在调用无参数构造函数或无参数静态工厂方法来实例化bean之后,通过容器调用bean上的setter方法来完成的。
2.对于可选的使用属性注入;
3.设值注入写法直观便于理解,使各种关系清晰明了。
4.设值注入可以避免因复杂的依赖实例化时所造成的性能问题。
5.设值注入的灵活性较强。 - 构造方法注入( Constructor-based Dependency Injection )
1.基于构造函数的DI是通过容器调用带有许多参数的构造函数来完成的,每个参数代表一个依赖项;
2.对于强制依赖的使用构造方法注入;
3.构造方法注入可以决定依赖关系的注入顺序,优先依赖的优先注入。
4.对于依赖关系无需变化的Bean,构造方法注入使所有的依赖关系全部在构造器内设定,可避免后续代码对依赖关系的破坏。
5.构造方法注入中只有组建的创建者才能改变组建的依赖关系,更符合高内聚原则。 - 建议
1.采用设值注入为主,构造注入为辅的注入策略。
2.有依赖则采用构造注入,其他则采用属性注入; - 注意:构造函数注入存在循环依赖问题!
7.spring 支持几种 bean 的作用域?
当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:
- singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例;
- prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例;
- request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效;
- session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效;
- globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效
8.spring 自动装配 bean 有哪些方式?
-
spring中bean装配有两种方式
1.隐式的bean发现机制和自动装配;
2.在java代码或者XML中进行显示配置 -
具体点
1.no:默认值,表示没有自动装配,应使用显式 bean 引用进行装配。
2.byName:它根据 bean 的名称注入对象依赖项。
3.byType:它根据类型注入对象依赖项。
4.constructor 构造函数:根据构造器进行装配,与 byType 类似,如果bean的构造器有与其他bean类型相同的属性,则进行自动装配;
5.autodetect:容器首先通过构造函数使用 autowire 装配,如果不能,则通过 byType 自动装配。
9.spring 事务实现方式有哪些?
- 编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
- 基于 TransactionProxyFactoryBean 的声明式事务管理;
- 基于 @Transactional 的声明式事务管理-
- 基于 Aspectj AOP 配置事务;
10.事务的特征
- 1.原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚; - 2.一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
eg:拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。 - 3.隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。 - 4.持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。
11.说一下 spring 的事务隔离级别(4种)?
- 因事务隔离级别可能产生的问题有? 场景:同一个事务内(同一个服务内)
1.脏读 :一个事务读到了另一个事务的未提交的数据;
2.不可重复读 :一个事务读到了另一个事务已经提交的 update 的数据导致多次查询结果不一致;
3.虚幻读 :一个事务读到了另一个事务已经提交的 insert 的数据导致多次查询结果不一致; -
设置事务的隔离级别(5种)?
1.DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
2.读未提交(read uncommited) :脏读,不可重复读,虚读都有可能发生;
3.读已提交 (read commited):避免脏读。但是不可重复读和幻读有可能发生;
4.可重复读 (repeatable read) :避免脏读和不可重复读.但是幻读有可能发生.
5.串行化的 (serializable) :避免以上所有读问题. - Mysql 默认:可重复读;Oracle 默认:读已提交;
12.spring事务7种传播行为?
propagation_XXX:事务的传播行为
- 保证同一个事务中
propagation_required: 支持当前事务,如果不存在 就新建一个(默认);
propagation_supports: 支持当前事务,如果不存在,就不使用事务;
propagation_mandatory: 支持当前事务,如果不存在,抛出异常; - 保证没有在同一个事务中
propagation_requires_new: 如果有事务存在,挂起当前事务,创建一个新的事务;
propagation_not_supported: 以非事务方式运行,如果有事务存在,挂起当前事务;
propagation_never: 以非事务方式运行,如果有事务存在,抛出异常;
propagation_nested: 如果当前事务存在,则嵌套事务执行;
13.spring 有哪些主要模块?

- Spring Core 提供bean工厂 IOC
Core封装包是框架的最基础部分,提供IOC和依赖注入特性。这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
- Spring Core 提供bean工厂 IOC
- Spring Context 提供了关于UI支持,邮件支持等
构建于Core封装包基础上的Context封装包,提供了一种框架式的对象访问方法,有些象JNDI注册器。Context封装包的特性得自于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明创建,比如说通过Servlet容器。
- Spring Context 提供了关于UI支持,邮件支持等
- Spring Dao JDBC支持
DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs(plain old Java objects)都适用。
- Spring Dao JDBC支持
- Spring ORM Hibernate|mybatis|JDO
ORM封装包提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate和iBatis。利用ORM封装包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。
- Spring ORM Hibernate|mybatis|JDO
- Spring AOP 面相切面编程
Spring的 AOP封装包提供了符合AOP Alliance规范的面向方面的编程实现,让你可以定义,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。而且,利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中。
- Spring AOP 面相切面编程
- Spring Web 提供了web的一些工具类的支持
Spring中的 Web 包提供了基础的针对Web开发的集成特性,例如多方文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。
- Spring Web 提供了web的一些工具类的支持
- Spring MVC 提供了web mvc , webviews , jsp ,pdf ,export
Spring中的MVC封装包提供了Web应用的Model-View-Controller(MVC)实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和Web Form之间。并且,还可以借助Spring框架的其他特性。
- Spring MVC 提供了web mvc , webviews , jsp ,pdf ,export
SpringMVC流程

1.用户发送请求至前端控制器DispatcherServlet。
2.DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3.处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4.DispatcherServlet调用HandlerAdapter处理器适配器。
5.HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6.Controller执行完成返回ModelAndView。
7.HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8.DispatcherServlet将ModelAndView传给ViewResolver视图解析器。
9.ViewReslover解析后返回具体View。
10.DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11.DispatcherServlet响应用户。
Spring mvc 有哪些组件?
- 前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CPU。
- 处理器映射器(HandlerMapping):根据URL去查找处理器
- 处理器(Handler):即后端控制器用controller表示。(需要程序员去写代码处理逻辑的)
- 处理器适配器(HandlerAdapter):会把处理器包装成适配器,这样就可以支持多种类型的处理器,类比笔记本的适配器(适配器模式的应用)
- 视图解析器(ViewResovler):进行视图解析,多返回的字符串,进行处理,可以解析成对应的页面
@RequestMapping 的作用是什么?
将 http 请求映射到相应的类/方法上。
用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
@Autowired 的作用是什么?
@Autowired 它可以对1.类成员变量、2.方法及3.构造函数进行标注,完成自动装配的工作,通过@Autowired 的使用来消除 set/get 方法。
鸣谢
Spring的构造函数注入的循环依赖问题
SpringMVC 运行流程
解释一下什么叫AOP(面向切面编程)
什么是IOC?
网友评论