Sping

[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&amp;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>

相關文章
相關標籤/搜索