***为什么要用spring
Rod Johnson 在设计 Spring 目的是,为了解决企业应用开发的复杂性,让 J2EE 开发更容易。
Spring 设计上的优点:
轻量级:相对于 EJB 这种重量级的容器而言,Spring 的 IOC 是完全不依赖底层容器,零侵入性的设计。便于开发测试,相对于 EJB 而言,Spring 部署方便,而且可以运行在任何 J2ee 支持的容器上,或者 APP 中。
控制反转(IOC):Spring 使用控制反转技术实现了松耦合,依赖被注入到对象,而不是创建或寻找依赖对象。
面向切面(AOP):解决了面向对象中不足,Spring 支持面向切面编程,同时把应用的业务逻辑与系统的服务分离开来。
事务管理:Spring 强大的事务管理功能,支持声明事务和编程事务,能够处理本地事务(一个数据库)或是全局事务(多个数据,采用 JTA)。
异常处理:由于 Java 的 JDBC,Hibernate 等 API 中有很多方法抛出的是 checked exception,而很多开发者并不能很好的处理异常。Spring 提供了统一的 API 将这些 checked exception 的异常转换成 Spring 的 unchecked exception。
SpringMVC 框架:Spring 实现了一个自己的 MVC 框架,性能优越性很高,可以替换 struts2,而且无需要考虑与 spring 整合问题。
由于 Spring 的优越性,得到了很大的用户青睐,尤其像阿里这样的大公司很注重Spring 的应用。
***简述一下spring结构
这个问题的答案就是用语言把下面这张图描述出来(把下面加黑的回答出来四五了就行了)。
1、核心容器
这是 Spring 框架最基础的部分,它提供了依赖注入(DependencyInjection)特征来实现容器对 Bean 的管理。这里最基本的概念是 BeanFactory,它是任何Spring 应用的核心。BeanFactory 是工厂模式的一个实现,它使用 IoC 将应用配置和依赖说明从实际的应用代码中分离出来。
2、应用上下文(Context)模块
核心模块的 BeanFactory 使 Spring 成为一个容器,而上下文模块使它成为事件传播以及验证的支持。
3、Spring 的 AOP 模块
Spring 在它的 AOP 模块中提供了对面向切面编程的丰富支持。这个模块是在Spring 应用中实现切面编程的基础。Spring 的 AOP 模块也将元数据编程引入了Spring。使用 Spring 的元数据支持,你可以为你的源代码增加注释,指示 Spring在何处以及如何应用切面函数。
4、JDBC 抽象和 DAO 模块
使用 JDBC 经常导致大量的重复代码,取得连接、创建语句、处理结果集,然后关闭连接。Spring 的 JDBC 和 DAO 模块抽取了这些重复代码,因此你可以保持你的数据库访问代码干净简洁,并且可以防止因关闭数据库资源失败而引起的问题。
5、对象/关系映射集成模块
对那些更喜欢使用对象/关系映射工具而不是直接使用 JDBC 的人,Spring 提供了 ORM 模块。Spring 并不试图实现它自己的 ORM 解决方案,而是为几种流行的 ORM 框架提供了集成方案,包括 Hibernate、JDO 和 iBATIS SQL 映射。Spring 的事务管理支持这些 ORM 框架中的每一个也包括 JDBC。
6、Spring 的 Web 模块
Web 上下文模块建立于应用上下文模块之上,提供了一个适合于 Web 应用的上下文。另外,这个模块还提供了一些面向服务支持。例如:实现文件上传的multipart 请求,它也提供了Spring 和其它Web 框架的集成,比如Struts、WebWork。
7、Spring 的 MVC 框架
Spring 为构建 Web 应用提供了一个功能全面的 MVC 框架。虽然 Spring 可以很容易地与其它 MVC 框架集成,例如 Struts,但 Spring 的 MVC 框架使用 IoC 对控制逻辑和业务对象提供了完全的分离。
***什么是IOC
IoC(Inversion of Control,控制反转)是 Spring 核心,它将之前需要在业务中维护的对象依赖关系交给 Spring 容器去管理,开发人员不需要去创建对象,只要在需要调用的地方直接去从容器中取就可以了,而这种原来由自己维护对象关系现在交给 Spring 容器来管理的方式就叫做 IOC。
***AOP 的实现原理
AOP 是一种面向过程的编程思想,它的实现原理主要是 Java 的动态代理,而 Spring 对动态代理的支持有两种方式,一种是默认的 JDK 实现,一种是 CGLIB 实现。
1、JDK 动态代理
Jdk 的动态代理是 Sping 的默认认实现,它要求必要是基于接口,代理类与被代理类必须实现同一个接口。
2、CGLIB 动态代理
Cglib 在 spring 的支持是需要在配置中指定(默认是通过 JDK 的方式实现),它不要求基于接口,它是通过子类继承的方式,利用回调来实现代理的。
***spring的生命周期
Spring 的生命周期其实就是 Bean 的生命周期,过程大概如下
1.容器启动,实例化所有实现了 BeanFactoyPostProcessor 接口的类。他会在任何普通 Bean 实例化之前加载.
2.实例化剩下的 Bean,对这些 Bean 进行依赖注入。
3.如果 Bean 有实现 BeanNameAware 的接口那么对这些 Bean 进行调用
4.如果 Bean 有实现 BeanFactoryAware 接口的那么对这些 Bean 进行调用
5.如果 Bean 有实现 ApplicationContextAware 接口的那么对这些 Bean 进行调用
6.如 果 配 置 有 实 现 BeanPostProcessor 的 Bean , 那 么 调 用 它 的postProcessBeforeInitialization 方法
7.如果 Bean 有实现 InitializingBean 接口那么对这些 Bean 进行调用
8.如果 Bean 配置有 init 属性,那么调用它属性中设置的方法
9.如 果 配 置 有 实 现 BeanPostProcessor 的 Bean , 那 么 调 用 它 的postProcessAfterInitialization 方法
10.Bean 正常是使用
11.调用 DisposableBean 接口的 destory 方法
12.调用 Bean 定义的 destory 方法
如果从大体上区分值分只为四个阶段
1.BeanFactoyPostProcessor 实例化
2.Bean 实例化,然后通过某些 BeanFactoyPostProcessor 来进行依赖注入
3.BeanPostProcessor 的调用.Spring 内置的 BeanPostProcessor 负责调用 Bean 实现的接口: BeanNameAware, BeanFactoryAware, ApplicationContextAware 等等,等这些内置的 BeanPostProcessor 调用完后才会调用自己配置的 BeanPostProcessor
4.Bean 销毁阶段
说明:如果感觉参考答案步骤太多难回答,可以只回答里面的下面四条,如果下面四条你嫌单词太长记不住,就回答我在解析里面的几个小步骤就行了。
***BeanFactory 和 ApplicationContext 区别
BeanFactory 负责读取 bean 配置文档,管理 bean 的加载,实例化,维护 bean之间的依赖关系,负责 bean 的声明周期。
ApplicationContext 除了提供上述 BeanFactory 所能提供的功能之外,还提供了更完整的框架功能:国际化支持、资源访问、事件传递等。
***spring实例化Bean的三种方式
1、通过构造来实例化 Bean,这也是 Spring 中最常用的,被实例化的 B ean 一定要有默认的构造方法,如果是有参构造,必须在 bean 的配置中指定构造参数, 否则 bean 将不能被实例化。
2、静态工厂,这个只需要在 bean 中指定属性 factory-method:参数为静态工厂类的生产对象的静态方法。
3、实例工厂,这个和静态工厂很相似,一般在 bean 中需要批定两个属性factory-bean:工厂类的实例; factory-method:工厂类生产对象的方法。
***Spring 各种事务实现及区别
从图中看 Spring 的事务配置包括三部分:DataSource,TransactionManager,代理机制。三种 DataSource 对应三种 TransactionManager 事务管理器,Spring 的五种事务配置其实这里指的是它的代理机制,关于代理机制这里目前不是我们讨论的重点,在面试中可以侧重它的事务支持来回答。
参考答案:
Spring 常用事务及实现原理,JDBC DataSource 中的事务是通过Connnection 来实现的,Hibernate 事务是用 session 来实现的,JTA 的事务一般是通过 JNDI 来实现的。除此外 JDBC 事务和 Hibernate 事务是对单一数据库操作, 通常不会同一个 Connection 来操作两个数据库, 而 Hibernate 中一般一个SessionFactory 对应一个数据库,更不会在一个 session 中操作两个数据库了;如果如果是访问不同的资源,上面的事物就不能满足了,这时必须选择 JTA 事务。而分布式部署则要使用 XA 事务才行。
***spring事务属性
事务的几种传播特性:
1.PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务,如果没有事务则开启。
2.PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务, 则非事务的。
3.PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4.PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
5.PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
6.PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异
7.PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按 TransactionDefinition.PROPAGATION_REQUIRED 属性执行。
Spring 事务的隔离级别:
1.ISOLATION_DEFAULT:这是一个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与 JDBC 的隔离级别相对应
2.ISOLATION_READ_UNCOMMITTED:这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
3.ISOLATION_READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数。
4.ISOLATION_REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5.ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行,除了防止脏读,不可重复读外,还避免了幻像读。
***Spring 编程事务与声明事务的区别
编程式事务一般的步骤是,开启手动事务、处理业务、提交事务、异常中回滚事务、finally 中关闭事务,在代码中需要手动完成;但我们这里提到的是 Spring中的编程事务,所以一般的做法是在 bean.xml 中声明一个事务类型、声明一个事务模板(注入声明的事务)、在业务 Service 中使用我们的事务模板。编程事务使用场景一般是事务比较简单且业务不复杂的的应用中推荐。
编程事务的优点: 容易控制边界,粒度细;缺点是,侵入性强。
声明式事务方式一(通过使用代理增加的方式配置):创建一个代理的工厂Bean(如 TransactionProxyFactoryBean),然后设置业务类接口属性,然后注入接口的实现类,然后注入事务管理器,然后注入事务属性(在上面已经提到,配置事务的隔离级别和传播特性);方式二(常用的),声明一个数据源,声明一个事务管理类,声明一个 Advice(设置一些 Spring 事务属性),定义切面指定事务的作用范围。
声明事务的优点是,侵入性性配置方便,缺点是边界不容易控制。
***springMVC的工作流程和原理
1、 用户发送请求至前端控制器DispatcherServlet
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、 执行处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、 ViewReslover解析后返回具体View
10、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户