Spring是什么
首先来说Spring是一个框架,它这里面自己封装完成了很多开发中的通用的一些步骤,并规范了其中一些步骤的使用,这样的话咱们开发的人就不用花太多的时间在特定应用以外的部分上面。
这样的话一方面它规范了企业的开发流程,而且还提高了开发效率。正因为它是整合了一些整个应用相关的通用步骤,因此它不区分到底是表现层,还是业务层,持久层,只要能简化的或者规范的它都给规范好了,并且很多地方Spring不会取代之前的优秀框架,而是更好的把它们无缝整合在一起,让他们更易用。
Spring的优点
- Spring的IoC容器使业务对象替换更加方便,直接在applicationContext.xml里面配置就可以,不用更改源代码,这样的话就提高了组件之间的解耦
- Spring的AOP可以将一些很多应用都有的通用任务比如说安全校验这块,还有事务啊,日志啊这些进行集中的处理,相当于更好的复用
- Spring的ORM和DAO都提供了与第三方持久层框架的整合,这样就简化了底层的数据库的访问
- Spring还有声明式的事务管理,不用手动编程,通过配置文件配置一下就能完成对事务的管理,它专门有一个Transactions模块,整合了JDBC啊,Hibernate啊,JPA等的事务,因为他们几个的事务开启跟关闭的代码都不一样,但是通过Spring就能统一的进行事务管理
- 还能方便程序的测试,因为Spring还整合了Junit来测试
- 还降低了JavaEE开发中非常难用的一些API的使用难度,比如JDBC啊,JAVAMail啊这些,因为Spring都提供了封装
Spring容器是什么(IOC容器)
其实Spring的核心容器就是一个超级大工厂,所有的对象(包括数据源啊,HibernateSessionFactory等基础性资源)都会被当成Spring核心容器管理的对象,里面的一切对象都被称为bean;只要在xml配置文件中配置的对象或者注解里面配置的对象都被这个容器管理
Spring的DI解释下
比如说配置文件里面配置了bean里面还有property标签,在容器通过反射的方式初始化了这个<bean../>之后,会再次以反射的方式调用setter为这个bean属性赋值,property的name属性决定执行哪个setter方法,value或者ref决定setter方法的传入参数(如果是基本数据类型及其包装类使用value属性传入参数,如果是容器中的其他bean,使用ref属性传入参数),这样应用启动的时候,创建了一批的bean,其中一些bean被当做属性赋值给其他的bean,其实你看,所有的java应用不管是小的Applet还是企业级的,这些应用中都会大量存在A对象需要调用B对象方法的情况,其实Spring把这种情况称之为依赖,也就是A依赖B,Spring通过配置文件的方式管理这种依赖关系,如果A依赖B,想调用B的方法,那么把B作为property赋值给A,这些Bean就被Spring以配置文件的方式组织在一起,而不是硬编码的方式耦合在一起,这就是依赖注入, DI(DependencyInsection)
其实依赖注入有两种:
属性注入,还有构造注入
Spring的IOC解释下
当某个JAVA对象(调用者)需要调用另外一个JAVA对象(被依赖对象)的方法时,传统模式下有两种做法:
- 一个是这个调用者主动创建被依赖对象,然后再调用被依赖对象的方法;
- 通过简单工厂模式:调用者先找到被依赖对象的工厂,然后主动通过工厂去获取被依赖对象,最后再调用被依赖对象的方法;
第一种方式显然需要通过new的方式创建被依赖对象,造成调用者与被依赖对象实现类的硬编码耦合,不利于项目的升级维护;第二种需要调用者面向被依赖对象的接口编程,调用者通过工厂获得被依赖组件,不会造成调用者与被依赖对象实现类的耦合,但是会造成调用者与被依赖对象工厂的耦合;
但是咱们使用Spring框架之后情况就不一样了,调用者不用再去主动获取被依赖对象,而是被动接受Spring容器为调用者的成员变量赋值(通过一个property标签就可以,Spring执行setter方法),由原来的主动获取变为被动接受,把这称之为控制反转;
Spring的传统AOP方式与AspectJ整合对比
其实Spring传统AOP里面已经定义了比如
前置通知 目标方法执行前增强 org.springframework.aop.MethodBeforeAdvice
后置通知 目标方法执行后增强 org.springframework.aop.AfterReturningAdvice
实现这些接口就相当于做了通知 advice 在Spring配置文件里面配置一堆的bean 这里面包括了Springframework下面的aop下面的PointCut类以及切面类Advisor 甚至ProxyFactoryBean都给设置好了
ProxyFactoryBean就是用工厂模式做出来的代理类
但是Spring整合Aspect之后,就可以用一个<aop:config/>标签来声明 切面以及切点就可以了
注意:advisor是传统的切面 aspect是aspectj的切面,有如下两种不同
<aop:advisor> 定义传统的aop的切面,传统的aop切面它只能包含一个切点与一个增强(而且传统的这种切面 用到的增强需要实现接口)
<aop:aspect>定义aspectj框架的切面.,它可以包含多个切点与多个通知(aspect 的这种切面不需要增强实现接口,只需要里面有对应的增强方法就行)
其中环绕通知是用的最多的,日志,事务,权限等等一个增强类下面可以对应多个切点
其实还可以使用注解@Aspect @Before()这类的注解,
需要在xml中配置aspectj的注解开启
介绍下SpringJDBCTemplate
pring提供了一个jdbc模板,它类似于dbutils工具。就是对平时jdbc操作的一个封装
它需要传入一个DataSource作为属性,因为它得用到这个连接池里面的方法连接到数据库,可以联想前面的IOC,如果没有Spring的话,调用者就得先创建这个DataSource,然后赋值到jdbcTemplate里面,但是有了Spring就不一样了,在Spring里面声明好,这里还用到了单例模式,例如DataSource就是个单例,哪个数据库都可以用,其实这里Spring内置了一个连接池DriverManagerDataSource
其实也可以使用其他的连接池 比如c3p0的连接池 jdbcTemplate都可以接收,而且数据库的配置可以放在外面
事务隔离的几种级别
ISOLATION_READ_UNCOMMITTED 不能解决问题,会发生脏读 不可重复读 虚读
ISOLATION_READ_COMMITTED 可以解决脏读 会产生不可重复读与虚读。(oracle默认的)
ISOLATION_REPEATABLE_READ 可以解决脏读,不可重复读 解决不了虚读 (mysql默认的)
ISOLATION_SERIALIZABLE 串行化,可以解决所有问题
不考虑隔离导致的几种问题
1. 脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
2. 不可重复读 :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不 可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果 只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。使用repeatableRead就可以重复读了,但是还不能杜绝幻读
3. 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。 如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。
事务的传播
它解决的是两个被事务管理的方法互相调用问题。它与数据库没关系,是程序内部维护的问题。 required 与 required_new
REQUIRED 如果有,用这一个,如果没有,创建一个新的
REQUIRES_NEW 如果之前已经存在一个transaction,那么就把之前的那个transaction挂起,并新建一个执行,等到这个新建的这个transaction执行完成后再去执行之前的那个transaction
Spring事务类型
编码式
不建议使用,它具有侵入性。在原有的业务代码基础上去添加事务管理代码
声明式
基于AOP对目标进行代理,添加around环绕通知。
这种方案,它不具有侵入性,不需要修改原来的业务代码,不是在原来代码基础上修改的
Spring 声明式事务管理
Spring中的声明式事务管理其实是基于传统的AOP,所以用aop:advisor ;并且不同的持久层对应不同的TransactionManager,例如jdbc以及mybatis的话就是用的DataSourceTransactionManager
这里不用配置增强(advice)了,事务管理器就是一个advice