[1].Sping 是什么java
Sping是一个开源的控制反转(Invarsion of Control IoC)和面向切面(AOP)的容器框架。
它的主要目的是简化企业开发。mysql
[2].IOC控制反转spring
public class PersonServiceBean{
private PersonDao personDao = new PersonDaoBean();sql
public void save(Person person){
personDao.save(person);
}
}数据库
PersonDaoBean 是在应用内部建立及维护的。所谓的控制反转就是
应用自己不负责依赖对象的建立及维护,依赖对象的建立及维护是有外部容器负责的。
这样控制权就由应用转移到了外部容器,控制权的转移就是所谓发转。express
[3].依赖注入(Dependency Injection)
当咱们把依赖对象交给外部容器负责建立,那么PersonServiceBean类能够修改以下:
public class PersonServiceBean(){
private PersonDao personDao;
//经过构造容器,让容器把建立好的依赖对象注入到PersonServiceBean中。
//固然也可使用setter方法进行注入
public PersonServiceBean(PersonDao personDao){
this.personDao= personDao;
}apache
public void save(Person person){
personDao.save(person)
}
}编程
所谓依赖注入就是指:在运行期间,由外部容器动态的将依赖对象注入到组件中。数组
[4].为什么要使用Spring
在项目中引入Spring能够带来如下好处:
1.减低组件之间的耦合度,实现软件各层之间的解耦。
Controller-->Service-->DAO
2.可使用容器提供众多的服务。如:事件管理服务,消息服务等等。
容器管理事务时,开发人员就再也不须要手工控制事务,也不须要处理复杂的事务传播。
3.容器提供单例模式支持,开发人员再也不下须要本身编写实现代码。
4.容器提供了AOP技术,利用它很容易实现如:权限拦截,运行期监控等功能。
5.容器提供的众多辅助类,使用这些类可以加快应用的开发,如:JdbcTemplate
HibernateTemplate。
6.Spring对于主流的应用框架提供了集成支持,如:集成Hibernate,JPA、struts。
这样便于应用的开发。session
[5].轻量级与重量级概念的划分
Spring框架是一个轻量级的框架仍是重量级的框架呢?
判断一个框架是轻量级仍是重量级,主要看它使用了多少服务,
使用的服务越多,容器要为普通java对象作的工做就越多,
必然会影响到应用的发布时间或者是运行性能。
对于Spring容器,它提供了不少服务,但这些服务并非默认都为应用打开的,
应用须要某种服务,还须要指明使用该服务,若是应用使用的服务不多,
如:只是用了spring的核心服务,那么此时应用属于轻量级的,若是应用使用了
Spring提供的大部分服务,这时应用就属于重量级。
[6]使用Spring须要jar文件
dist\spring.jar
lib\jakarta-commons\commons-logging.jar
若是使用了切面编程(AOP),还须要下列jar文件
lib/aspectj/aspectjweaver.jar和aspect.jar
[7]Spring的配置文件模板
<?xml version="1.0" encoding="UTF-8">
<beans xmlns="" xmlns="" xsi:schemaLocation="">
<bean>
</bean>
</beans>
该配置模板能够从Spring的参考手册或spring的例子中获得,配置我呢见的
取名能够任意,文件能够存放在任何目录写下,但考虑到通用性,通常放在
类路径下。
[8]实例化SPRING容器
实例化Spring容器经常使用的两种方式:
1.在类路径下寻找配置文件来实例化容器。
ApplicationContext ctx = new
ClassPathXmlApplicationContext(new String[]{"beans.xml"});
2.在文件系统路径下寻找配置文件来实例化容器
ApplicationContext ctx = new
FileSystemXmlApplicationContext(new String[]{"d:\\beans.xml"});
考虑到应用的可移植性,建议使用第一种方式。spring的配置我呢见能够指定多个,
能够经过Sring数组导入。
PersonService.clsss
public interface PersonService{
public void save(){};
}
PersonServiceBean.clsss
public class PersonServiceBean implements PersonService{
public void save(){
System.out.println("hello");
};
}
<!--beans.xml-->
<bean id="personService" clas"cn.soldier.service.imp.PersonServiceBean"></bean>
Test.class
@Test
ApplicationContext ctx = new
ClassPathXmlApplicationContext(new String[]{"beans.xml"});
PersonService personService =(PersonService) ctx.getBean(personService);
personService.save()
[9]三种实例化Bean的方式
1.使用类构造器实例化 99%
<!--beans.xml-->
<bean id="personService" clas"cn.soldier.service.imp.PersonServiceBean" />
2.使用静态工厂方法实例化
<!--beans.xml-->
<bean id="personService2"
clas"cn.soldier.service.imp.PresonServiceBeanFactory"
factory-method="createPresonServiceBean" />
<!--OrderFactory.class-->
public class PresonServiceBeanFactory{
public static PresonServiceBeanFactory createPresonServiceBean{
return new PresonServiceBean();
}
}
3.使用实例工厂方法实例化
<!--beans.xml-->
<bean id="personServiceFactory"
class="cn.soldier.service.imp.PresonServiceBeanFactory" />
<bean id="personService3" factory-bean="personServiceFactory"
factory-method="createPresonServiceBean2" />
<!--OrderFactory.class-->
public class PresonServiceBeanFactory{
public PresonServiceBean createPresonServiceBean2{
return new PresonServiceBean();
}
}
[10]bean的做用域
singleton
每一个Spring Ioc容器中一个bean定义只有一个对象实例。默认状况下会在容
器启动时初始化bean。但咱们能够指定Bean节点的lazy-init="true"来延迟
初始化bean,这时候,只有第一次获取bean才会初始化。
如:
<bean id="xxx" class="cn.soldier.OrderServiceBean" lazy-init="true" />
若是你相对全部bean都应用延迟初始化。能够在根节点beans设置
default-lazy-true。以下:
<beans default-lazy-init="true">
prototype
每次从容器获取bean都是新的对象
用法以下
<bean id="xxx" clas"cn.soldier.OrderServiceBean" scope="prototype" />
request
session
global session
[11]指定bean的初始化方法和销毁方法
<bean id="xxx" clas"cn.soldier.OrderServiceBean"
init-method="init" destroy-method="close" />
[12]注入依赖对象
基本类型对象注入:
<bean id="orderService" class="cn.soldier.OrderServiceBean">
<constructor-arg index="0" type="java.lang.String" value="xxx" />//构造器注入
<property name="name" value="zhao" /> 属性setter方式注入
</bean>
注入其余bean
方式一:
<bean id="orderDao" class="cn.soldier.OrderDaoBean" />
<bean id="orderService" class="cn.soldier.OrderServiceBean">
<property name="orderDao" value="orderDao" />
</bean>
方式二:(使用内部bean,但该bean不能被其余bean使用)
<bean id="orderService" class="cn.soldier.OrderServiceBean">
<property name="orderDao" >
<bean id="orderDao" class="cn.soldier.OrderDaoBean" />
</property>
</bean>
[13]集合类型的装配
public class OrderServiceBean{
private Set<String> sets = new HashSet<String>();
private List<String> lists = new ArrayList<String>();
private Properties<String> properties = new Properties();
private Map<String,String> maps = new HasMap<String,String>();
//这里省略属性的getter和setter方法
}
<bean id="orderService" class="cn.soldier.OrderServiceBean">
<!--Set类型注入-->
<property name="sets">
<set>
<value>第一个</value>
<value>第二个</value>
<value>第三个</value>
</set>
</property>
<!--List类型注入-->
<property name="lists">
<list>
<value>第一个</value>
<value>第二个</value>
<value>第三个</value>
</list>
</property>
<!--Properties注入-->
<property name="properties">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
<prop key="key3">value3</prop>
<props>
</property>
<!--Map类型注入-->
<property name="maps">
<map>
<entry key="key1" value="value1" />
<entry key="key2" value="value2" />
<entry key="key3" value="value3" />
</map>
</property>
</bean>
[14]依赖注入
使用构造器注入
使用属性setter方法注入
使用Field注入(用于注解方式)
使用构造器注入
<bean id="orderService" class="cn.soldier.OrderServiceBean">
<constructor-arg index="0" type="java.lang.String" value="xxx" />//构造器注入
<constructor-arg index="1" type="cn.soldier.OrderDao" ref="orderDao" />//构造器注入
</bean>
使用属性setter方法注入
<bean id="orderService" class="cn.soldier.OrderServiceBean">
<property name="id" value="1001" /> 属性setter方式注入
<property name="name" value="liangxin" /> 属性setter方式注入
</bean>
注入依赖对象能够采用手工装配或自动装配,在实际应用中建议使用手工装配,
由于自动装配会产生未知状况,开发人员没法预见最终装配结果
1.手工装配依赖对象
2.自动装配依赖对象
[15]依赖注入--手工装配
手工装配依赖对象,在这种方式中又有两种编程方式
1.在xml配置文件中,经过bean节点配置。
以下:
<bean id="orderService" class="cn.soldier.service.OrderServiceBean">
<constructor-arg index="0" type="java.lang.String" value="xxx" />//构造器注入
<property name="name" value="zhao" /> 属性setter方式注入
</bean>
2.在java代码中使用[@Autowired]或[@Resource]注解方式进行装配。但我么们须要先
在xml文件中配置如下信息:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsl:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
</beans>
这个配置隐式注册了多个对注释进行解析处理的处理器:
AutowiredAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor,
RequiredAnnotationBeanPostProcessor
注:[@Resource]注解在spring安装目录的lib\j2ee\common-annotations.jar
在java代码中使用 [@Autowired] 、 [@Resource] 方式进行装配,这两个注释的区别是
@Autowired 默认按类型装配
@Resource 默认使用安名称装配,当找不到与名称匹配的bean时才会安类型转配
例子以下:
@Autowired //用于字段上
private PersonDao personDao;
@Autowired //用于属性的setter方法上
public void setOrderDao(OrderDao orderDao){
this.orderDao = orderDao;
}
@Autowired注解是按类型装配依赖对象,默认状况下它要求依赖对象必须存在。
若是容许null值,能够设置它的required属性为false。
若是想使用按名称装配,能够结合 [@Qualifier] 注解一块儿使用.
例子以下:
@Autowired @Qualifier["personDaoBean"]
private PersonDao personDao;
@Resource 注解和 @Autowirde 注解同样,也是能够标注在字段或属性的setter
方法上,但它默认按名称装配。名称能够经过 @Resource 的name属性指定,若是
没有指定name属性,当注解在字段上,即默认取字段的名称做为bean名称寻找依赖对象
当注解在属性的setter方法上,即默认取属性名做为bean名称寻找依赖对象。
@Resource(name="personDaoBean")
privte PersonDao personDao; //用于字段上
注意: @Resource 若是没有指定属性名,而且按照默认名称仍然找不到依赖对象时,
@Resource注解会回退到按类型匹配,但一旦指定了name属性,就只能按名称装配了。
[16]依赖注入--自动装配依赖对象
对于自动装配,你们了解一下就能够了。
例子以下
<bean id="" class="" autowire="byType" />
autowire属性取值以下:
byType:按类型匹配,能够根据属性的类型,在容器中寻找跟该类型匹配的bean。
若是发现多个,那么将会抛出异常。若是没有找到,那么属性值为null。
byName:按名称装配,能够根据属性的名称,在容器中寻找跟该属性名相同的bean。
若是没有找到,那么属性值为null。
constructor:constructor与byType方式类似,不一样之处在于它应用构造器参数。
若是没有找到与构造器参数类型一直的bean,那么将会抛出异常。
autodetect:经过bean类的自省机制(introspection)来决定使用constructor仍是
byType方式进行自动装配,<!--若是发现有默认的构造器,那么将使用byType方式-->
[16]经过在classpath自动扫描方式把组件归入spring容器中管理
前面的例子咱们都是使用XML的bean定义配置组件的。在一个稍大的项目中,一般会
有上百个组件,若是这些组件采用xml的bean定义来配置,显然会增长配置文件的体积
并且查找和维护起来也不太方便。使用自动扫描机制,它能够在类路径下寻找标注了
@Component @Service @Controller @Repository注解的类,并把这些类归入进spring
容器中管理。它的做用和xml文件使用bean节点配置组件是同样的。
要使用自动扫描机制,咱们须要设置一下配置信息
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsl:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="cn.soldier" />
<!--包含了这个处理器 <context:annotation-config /> -->
</beans>
其中base-package为须要扫描的包(包含子包)
@Component 泛指组件,当组件很差归类的时候,可使用这个注释进行标注
@Service 用于标志业务层组件
@Controller 用于标注控制层组件(如struts的action)
@Repository 用于标注数据访问组件 即DAO层
@Service("xxxx")
更名为xxxx
public class OrderServiceBean{
}
@Service @Scope("proptotype")
改成原型做用域,默认是单例
public class OrderServiceBean{
}
@PostConstruct //初始化注解
public void init(){
}
@PreDestory //注销注解
public void destory(){
}
[17]AOP中的概念
Aspect(切面):指横切性关注点的抽象。即为切面,它与类类似。只是二者的关注点
不同,类是读物体特征的抽象,而切面是横切性关注点是抽象。
Joinpoint(链接点):所谓链接点是指那些被拦截到的点。在Spring中,这些点值得是
方法,由于spring只支持方法类型的链接点,实际上joinpoint仍是field或类构造器
Pointcut(切入点):所谓切入点是咱们对那些joinpoint进行拦截的定义
Advice(通知):所谓通知是指拦截到joinpoint以后所要作的事情就是通知,通知分
前置通知,后置通知,异常通知,最终通知,环绕通知
Target(目标对象):代理的目标对象
Weave(织入):指将aspects应用到target对象并致使proxy对象建立的过程
IntroDuction(引入):在不修改类代码的前提下,Introduction能够运行期为类动态的
添加一些方法或field
[18]使用Spring进行面向切面编程
要进行aop编程,首先咱们要在Spring的配置文件中导入aop命名空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/aop"
xsl:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
</beans>
Spring 提供了两种面向切面使用方式,实际工做中咱们能够选用其中一种,
1.基于XML配置方式的AOP开发
2.基于注解方式的AOP开发
[19]基于注解方式声明切面
1.首先启动 @AspertJ注解的支持
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsl:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy />
<bena id="rderservise" class="" />
<bena id="rderservise" class="" />
</beans>
2。定义好切面
3.交给Spring管理
<bena id="myInterceptor" class="cn.soldier.service.MyInterceptor" />
//定义切面
@Aspect
public class LogPrint{
@Pointcut("ececution(* cn.soldier.service..*.*(..))") //
private void anyMethod{}//声明一个切入点
@Before("anyMethod() && args(userName)")//定义前置通知
public void doAccessCheck(String userName){
}
@AfterReturning(pointcut="anyMethod()",returning="revalue")//定义后置通知
public void doReturnCheek(String revalue){
}
@AfterThroving(pointcut="anyMethod()",throwing="ex")//定义例外通知
public void doExceptionAction(Exception ex){
}
@After("anyMethod()")//定义最终通知
public void doReleaseAction(){
}
@Around("anyMethod()")//环绕通知
public Object doBasicProfiling(ProceedingJoinPotint pjp) throws Throwable{
//if(){//判断用户是否有权限
Object result = pjp.proceed();
//}
return result;
}
}
@Pointcut"ececution(* cn.soldier.service..*.*(..))
ececution //执行
(
*//返回值类型
cn.soldier.service//哪一个包
..//子包也拦截
*//哪一个类
.*//哪一个方法,
(..)//哪些参数
)
这里表示的是对于cn.soldier.service包及其子包下的全部
类的任意返回值的全部方法的进行拦截。
[19]基于xml配置方式声明切面
//定义切面
<bean id="orderservice" class="cn.soldier.service.OrderServiceBean" />
<bean id="log" class="cn.soldier.service.LogPrint" />
<aop:config>
<aop:aspect id="myaop" ref="log">
<aop:pointcut id="mycut" experssion="execution(* cn.soldier.service..*.*(..))" />
<aop:before pointcut-ref="mycut" method="doAccessCheck" />
<aop:after-returning pointcut-ref="mycut" method="doReturnCheck" />
<aop:after-throwing pointcut-ref="mycut" method="doExceptionAction" />
<aop:after pointcut-ref="mycut" method="doReleaseAction" />
<aop:around pointcut-ref="mycut" method="doBasicProfiling" />
</aop:aspect>
</aop:cinfig>
public class LogPrint{
public void doAccessCheck(String userName){
System.out.println("前置通知");
}
public void doReturnCheck(){
System.out.println("后置通知");
}
public void doReleaseAction(){
System.out.println("最终通知");
}
public void doExceptionAction()
System.out.println("例外通知");
}
public Object doBasicProfiling(ProceedingJoinPotint pjp) throws Throwable{
System.out.println("环绕通知");
//if(){//判断用户是否有权限
Object result = pjp.proceed();
//}
return result;
}
}
[20]Spring--JDBC 组合开发
使用Spring+JDBC集成步骤以下:
1.配置数据库,如:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSpource"
destroy-method="close"><!--destroy-method="close"设置为单例-->
<property name="driverClassNamme" value="org.gjt.mm.mysql.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/soldier?
useUnicode=true&characterEncoding-UTF-8" />
<property name="username" value="root" />
<property name="password" value="123456"
<!--链接池启动时的初始值-->
<property name="initialSize" value="1" />
<!--链接池的最大值-->
<property name="maxActive" value="500" />
<!--最大空闲值,当通过一个高峰时间后,链接池能够慢慢将已经用不到的链接慢慢释
放一部分一直减小到maxIdle为止-->
<property name="maxIdle" value="2" />
<!--最小空闲值,当经空闲的链接邵谊阀值时,链接池就会申请一些链接,
以避免洪峰来时来不及申请-->
<property name="minIdle" value="1" />
</bean>
2.配置事务
配置事务时,须要在xml配置文件中引入用于声明事务的tx命名空间,
事务的配置方式有两种:注解方式和基于XML配置方式。
[21]使用注解方式配置事务
1.声明tx命名空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsl:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
</beans>
2.配置bean
<bean id="txManager" class="org.springframework.jdbc.datasource
.DataSorceTransaction.Manager">
<property name="dataSource" ref="dataSource" /><!--配置数据源-->
</bean>
3.采用组件
<!--采用 @Transaction注解方式使用事务-->
<tx:annotationn-driver transaction-manager="txManager" /><!-- transaction-manager 配置事务管理器-->
PersonServiceBean.class
@Service @Transactional
public class PersonServiceBean implements PersonService{
}
[22]使用JdbcTemplate获取一条记录
@Service @Transaction
public class PersionServiceBean implements PersonService{
Private JdbcTemplate jdbcTemplate;
@Resource
public void setDataSourse(DataSource dataSource){
this.jdbcTemplate = new JdbcTemllate(dataSource);
}
public Person getPerson(Integer id){
RowMaooer rowMapper = new RowMapper(){
public Object mapRow(ResuleSet rs,int rowNum) throws SQLException{
Person person = new Person();
person.setId(rs.getInt("id"));
person.getName(re.getString("name"));
return person;
}
};
String sql ="SELECT * FROM person WHERE id=?"
return (Person)jdbcTemplate.queryForObject(sql,new Object[]{id},
new int[]{java.sql.Types.INTGER},rowMapper);
}
}
[23]使用JdbcTemplate获取多条记录
@Service @Transactional
public class PersonServiceBean implements PersonService{
pirvate JdbcTemplate jdbcTemplate;
@Resource
public void setDataSource(DataSource dataSource){
this.jdbcTemplate = new JdbcTempleate(dataSource);
}
public List<Person> getPersons(){
RowMaooer rowMapper = new RowMapper(){
public Object mapRow(ResuleSet rs,int rowNum) throws SQLException{
Person person = new Person();
person.setId(rs.getInt("id"));
person.getName(re.getString("name"));
return person;
}
};
String sql = "SELCET * FROM person";
return jdbcTemplate.query(sql,rowMapper);
}
}
<!--jdbc.properties-->
driverClassNamme=org.gjt.mm.mysql.Driver
url=jdbc\:mysql\://localhost\:3306/soldier?useUnicode\=true&characterEncoding\=UTF-8" />
username=root
password=123456
initialSize=1
maxActive=500
maxIdle=2
minIdle=1
bean.xml
使用属性占位符配置上面的数据源
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsl:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:property-placeholder location ="classpath: jdbc.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSpource"
destroy-method="close"><!--destroy-method="close"设置为单例-->
<property name="driverClassNamme" value="${driverClassNamme}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}"
<!--链接池启动时的初始值-->
<property name="initialSize" value="${initialSize}" />
<!--链接池的最大值-->
<property name="maxActive" value="${maxActive}" />
<!--最大空闲值,当通过一个高峰时间后,链接池能够慢慢将已经用不到的链接慢慢释
放一部分一直减小到maxIdle为止-->
<property name="maxIdle" value="${maxIdle}" />
<!--最小空闲值,当经空闲的链接邵谊阀值时,链接池就会申请一些链接,
以避免洪峰来时来不及申请-->
<property name="minIdle" value="${minIdle}" />
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource
.DataSorceTransaction.Manager">
<property name="dataSource" ref="dataSource" /><!--配置数据源-->
</bean>
<tx:annotationn-driver transaction-manager="txManager" />
<!-- transaction-manager 配置事务管理器-->
</beans>
[24]事务传播属性
REQUIRED:
特务方法须要在一个事务中运行。若是方法运行时,已经处在一个事务中,那么
加入该事务,不然为本身建立一个事务。
NOT_SUPPORTED:
声明方法不须要事务,若是方法没有关联到一个事务中,容器不会为它开启事务,若是
方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,
原先的事务便会恢复执行。
REQUIRESNEW:
属性代表不论是否存在事务,业务方法总会为本身发起一个新的事务,若是方法已
经运行在一个事务中,则原先的事务会被挂起,新的事务会被建立,直到方法执行结束
新的事务才算结束,原先的事务才会恢复执行。
MANDATORY:
该属性指定业务防范只能在一个已经存在的事务中执行,业务方法不能发表本身的事务。
若是业务方法在事务范围外被调用,则方法在没哟偶事务的环境下执行行。
SUPPORTS:
这一书屋属性代表。若是业务方法在某个事务范围内被调用,则方法称为该是唔的一部分,
若是业务方法在事务范围外被调用,则方法在没有事务的环境下执行。
Never:
指定业务放大绝对不能再事务范围内执行,若是业务方法在某个事务中执行,容器会抛出
例外,只有业务方法没哟偶关联到任何事务,才能正常执行。
NESTED:
若是一个活动的事务存在,则运行在一个嵌套的十五中,若是没有活动事务则按
REQUIRDE属性执行,他使用了一个单独的事务。这个事务用用多个回滚的保存掉,内部
事务的回滚不会对外部事物形成影响,它只对DataSourceTransactionManager事务管理器
起效。
@Transactional(noRollbackFor=RuntimeException.class) //即便发生异常也不回滚
public void delete(Integet personid) throws Exception{
throws new RuntimeException("运行期例外");
}
@Transactional(rollbackFor=RuntimeException.class) //发生异常回滚
public void delete(Integet personid) throws Exception{
}
@Transactional(propagetion=Propagation.NOT_SUPPPRTED)//注明不须要事务管理
public Person getPerson(Integet personId){
}
[25]事务传播属性NESTED介绍
@Resource OtherService otherService;
public void xxx(){
String sql ="UPDATE person SET name='888' WHERE id=1";
stmt.executeUpdate(sql);
sql = "UPDATE person SET name='222' WHERE id=2";
stmt.executeUpdate(sql);
otherService.update();//OtherService的update方法的事务传布属性为NESTED
sql ="DELETE FROM person WHERE id=9";
stmt executeUpdate(sql);
}
上面 xxx()的内部执过程
public void xxx(){
Connection conn = null;
try{
conn.setAutoCommit(false);
Statement stmt =conn.createStatement();
String sql ="UPDATE person SET name='888' WHERE id=1";
stmt executeUpdate(sql);
SavePoint savapoint = conn.setSavepotion();//Spring容器生成
try{
String temp = "UPDATE person SET name='222' WHERE id=2";
conn.createStatement().executeUpdate(sql);
}catch(Exception ex){
conn.rollvack(savepoint);//Spring容器生成
}
sql ="DELETE FROM person WHERE id=9";
stmt executeUpdate(sql);
}catch(Exception ex){
conn.rollvack(); //Spring容器生成
}finally{
try{
if(null != conn && !conn.IsClose())
conn.close();
}catch(SQLException e){
e.printStackTrece();
}
}
}
[26]数据库提供的四种事务隔离级别
数据库系统提供了四种事务隔离级别供用户选择,不一样的隔离级别采用不一样的锁类型来
实现,在四种隔离级别中,Serializble的隔离级别最高,Read Uncommited的隔离级别
最低,大多数数据库默认的隔离级别为Read Commited如SQLSERVER 2000。固然也有少部分
的隔离级别是Repeatable Read,如 MYSQL
Read Uncommited 读未提交数据(会出现脏读,不可重复读和幻读)
Read Commited 读已提交的数据(会出现不可重复读和幻读)
Repeatable Read 可重复读(会出现幻读)
Serializble 串行化
脏读:就是一个事务读取到另外一个事务为提交的更新数据。
不可重复读:就是在一个事务中,屡次读取同一数据返回的结果有所不一样。
换句话说就是,后续读取能够读到另外一事务已提交的数据。
可重复读:就是在同一个事务中,屡次读取数据时,可以保证所读取数据时同样的,
也就是后续读取不能读到另外一事务已提交的更新数据。
幻读:就是一个事务读取到另外一事务已提交的insert数据。
[27]基于XML方式配置事务
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSoource">
</bean>
<!--配置aop,拦截全部方法cn.soldier.servlce..*.*(..),交给txAdvice事务通知处理-->
<aop:config>
<aop:pointcut id="transactionPointcut" expression="execution(* cn.soldier.servlce..*.*(..))"/>
<aop:adivsor adiver-ref="txAdvice" pointcut-ref="transactionPointcut" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager" /> <tx:attributes> <!--若是拦截以get开头的方法,不须要事务 --> <tx:method name="get*" read-only="true" propagaction="NOT_SUPPORTED" /> <!--其余方法,使用事务的默认行文,数据库隔离级别使用数据库的默认隔离级别 --> <tx:method name="*" /> </tx:attributes></tx:advice>