Spring邊學習邊總結

 

1.Spring介紹:
事務傳播行爲:多個業務bean方法要求在同一個事務中發生,如:

public void pay()
{
bean1.update();
bean2.save();
} 
解決方法是將conn對象傳遞給兩個bean對象,這樣就可以在同一數據庫連接進行事務管理了:
public void pay()
{
Connection conn=...
conn.setAutoCommit(false);
bean1.update(conn);
bean2.save(conn);
}
 同時不管bean1.update()是否成功,要求bean2.save()不受影響,這些都可以利用spring來解決(聲明式事務管理)

2.Spring配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="personService" class="com.zxf.service.impl.PersonServiceBean">//調用默認構造函數

</bean>


</beans>id不能包含特殊字符,name可以包含特殊字符

junit測試方法:

@Test public void instanceSpring(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");//
PersonService ps = (PersonService)applicationContext.getBean("personService");
ps.save();
}

3.Spring實例化bean的原理:

ClassPathXmlApplicationContext讀取配置文件獲得每一個需要實例化的bean的id和對應的類,在讀取一個bean的信息後,會在容器中爲它實例化一個帶兩個實例域的bean(private string id;private string class),並將所有裝有所有bean信息的對應的bean都放入一個map內。在從該map裏面取出信息bean,利用反射將bean實例化,存入容器,應用spring容器的程序就可以通過getBean方法來獲得相應的bean.

4.三種實例化bean的方法:

上面一種;
靜態工廠類實例化:

<bean id="personService2" class="com.zxf.service.impl.PersonServiceBeanFactory" factory-method=">
實例工廠類實例化:
<bean id="personServiceFactory" class="com.zxf.service.impl.PersonServiceBeanFactory">
</bean>
<bean id="personService3" factory-bean="personServiceFactory" factory-method="createPersonServiceBean2">
</bean>

5.bean的作用域:Singleton(同一實例) | Prototype(新實例)

PersonService ps1 = (PersonService)applicationContext.getBean("personService");
PersonService ps2 = (PersonService)applicationContext.getBean("personService");
System.out.println(ps1 == ps2);//true所以默認情況下容器爲bean保存唯一實例
獲得不同的實例:
<bean id="personService4" class="com.zxf.service.impl.PersonServiceBean" scope="prototype">
</bean>
6.bean的作用域:
實例化:默認(singleton情況下)是在spring容器實例化的時候也就是ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");的時候;但是如果這時設置了lazy_init="true"則會在getBean的時候實例化。;
prototype情況下:是在調用getBean的時候實例化.

7.爲bean指定初始化和銷燬執行的方法:

<bean id="personService5" class="com.zxf.service.impl.PersonServiceBean" scope="prototype" init-method="init" lazy-init="true"destroy-method="des">
</bean>
8.依賴對象的注入:PersonServiceBean 依賴 PesonDaoBean(PersonServiceBean的實例域)
<bean id="personDao" class="com.zxf.dao.impl.PersonDaoBean">
</bean>
<bean id="personService7" class="com.zxf.service.impl.PersonServiceBean">
<property name="personDao" ref="personDao"></property>
</bean>

9.依賴注入的原理:
spring爲每一個bean的property創建一個保存信息的PropertyDefinitionBean,一個bean應該會對應多個PropertyDefinitionBean,所以可以在前面定義BeanDefinitionBean中用一個集合來存放多個PropertyDefinitionBean,當利用BeanDefinitionBean和反射實例化一個bean的時候,同時會根據BeanDefinitionBean中的PropertyDefinitionBean的集合來從容器中指定相應的所依賴的bean,因爲比如說personDao這個bean已經在容器中實例化,不需要再實例化,只需要指定就可以了,再利用反射就可以對bean所依賴的對象進行注入了。過程是先實例化bean,再來爲它注入對象,得到bean的所有屬性信息,再與配置文件進行比較,如果配置文件中配置的屬性在bean定義中不存在,就不會爲它注入。注意<property name="personDao" ref="personDao"></property>
裏面的name的名字必須與bean定義中的依賴對象名相同,否則會注入失敗(private PersonDao personDao)。

10.注入方式:
上面一種;(可以被多個bean重用)
內部bean:(只能被單個的bean使用,估計是注入內部bean的時候沒有將實例化的內部bean放入spring容器,只是一個臨時對象bean)

<bean id="personService8" class="com.zxf.service.impl.PersonServiceBean">
<property name="personDao">
<bean class="com.zxf.dao.impl.PersonDaoBean" />
</property>
</bean>
爲基本數據類型注入值:
<bean id="personService8" class="com.zxf.service.impl.PersonServiceBean">
<property name="personDao">
<bean class="com.zxf.dao.impl.PersonDaoBean" />
</property>
<property name="name" value="曾險峯"/>
<property name="age" value="21"/>
<property name="height" value="178"/>
</bean>
集合類型的注入:一般需要在注入對象的定義中指定一個集合類,如:
Private Set<String> sets = new HashSet<String>();
Private List<String> lists = new ArrayList<String>();
Set集合類型注入:
<bean id="personService9" class="com.zxf.service.impl.PersonServiceBean">
<property name="sets">
<set>
<value>sets第一個</value>
<value>sets第二個</value>
<value>sets第三個</value>
</set>
</property>
</bean>
List集合類型注入:
<bean id="personService10" class="com.zxf.service.impl.PersonServiceBean">
<property name="lists">
<list>
<value>lists第一個</value>
<value>lists第二個</value>
<value>lists第三個</value>
</list>
</property>
</bean>
Properties類型注入:
<bean id="personService11" class="com.zxf.service.impl.PersonServiceBean">
<property name="property">
<props>
<prop key="key1">properties第一個</prop>
<prop key="key2">properties第二個</prop>
<prop key="key3">properties第三個</prop>
</props>
</property>
</bean>
Map類型注入:
<bean id="personService12" class="com.zxf.service.impl.PersonServiceBean">
<property name="maps">
<map>
<entry key="key1" value="map第一個"></entry>
<entry key="key2" value="map第二個"></entry>
<entry key="key3" value="map第三個"></entry>
</map>
</property>
</bean>

11.構造器注入:(前面用的都是setter方法注入)

<bean id="personService13" class="com.zxf.service.impl.PersonServiceBean">
<constructor-arg index="0" value="構造器注入" />
<constructor-arg index="1" type="com.zxf.dao.PersonDao" ref="personDao" /> 
</bean>
注意這裏的type因爲構造器定義是
public PersonServiceBean(String name, PersonDao personDao) {
this.name = name;
this.personDao = personDao;
}
所以type不能指定爲"com.zxf.dao.impl.PersonDaoBean"儘管personDao是"com.zxf.dao.impl.PersonDaoBean"的實例,但是子類引用不能指向父類對象。

13.使用註解進行注入:需要添加以下配置信息:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi: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>

@Autowired默認按類型裝配
@Autowired
private UserDao userDao;//字段上添加註解
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}//setter注入
也可以指定名稱注入。不過只能應用於字段
@Autowired(required=true) @Qualifier("userDao")
private UserDao userDao;//required=true要求該依賴對象必須注入。
@Resource默認按名稱裝配,按名稱無法裝配的時候則按類型
@Resource
private UserDao userDao2;//字段注入,然後會在配置文件中找名爲userDao2的bean進行注入,否則會找UserDao類型的bean進行注入
@Resource(name="userDao_2")
public void setUserDao2(UserDao userDao2) {
this.userDao2 = userDao2;
}//setter方法注入,可以指定name屬性,用於尋找名爲name 的bean
一般推薦用@Autowired進行注入!

13.注入方式:手工裝配和自動裝配
自動裝配:

<bean id="userService" class="com.zxf.service.impl.UserServiceBean" autowire="autodetect">
autodetect 自動裝配。

14.通過利用classpath自動掃描方式把組件納入容器管理:配置:

<context:component-scan base-package="com.zxf"></context:component-scan>
@Service--Service層
@Controller--控制層
@Component--一般組件
@Repository--DAO層
---------------------------------
@Service//("userService")//@Scope("prototype")
public class UserServiceBean implements UserService;
@Repository//("userDao")//@Scope("prototype")
public class UserDaoBean implements UserDao;
這樣就已經將bean交給Spring管理了,Spring可以通過getBean()方法得到bean,默認的名稱是類名的第一個字母變爲小寫就可以了,同時還可以像上面那樣指定名稱。由於默認的情況下,這些被實例化出來的bean的作用域是singleton的,所以需要額外的指定註解來改變作用域,如上面的@scope。

15.在Spring自動管理Bean的情況下,指定bean的初始化方法:

@PostConstruct
public void init(){
System.out.println("初始化方法開始");
}
指定銷燬方法:
@PreDestroy
public void destroy(){
System.out.println("關閉資源");
}

16.J2SE動態代理實現攔截:目標對象必須實現接口,否則不能應用Proxy,比如

public class UserServiceBean implements UserService
代理類也會實現同樣的接口,並且會在實現方法中調用目標對象相應的方法
public class JDKProxyFactory implements InvocationHandler {
private Object targetObject;

public Object createProxyObject(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
this.targetObject.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = method.invoke(targetObject, args);
return null;
}
}//創建的代理對象中有一個實例域存放InvocationHandler 的對象;

當客戶端調用代理對象時,代理對象會執行InvocationHandler對象的invoke方法,將方法調用委派給目標對象。

UserService userService = (UserService)factory.createProxyObject(new UserServiceBean("曾險峯"));
userService.save("Teeny");
上述代碼返回的是一個實現了UserService接口的代理對象,通過它來調用目標對象方法時,會調用InvocationHandler.invoke()方法,可能是如下形式
public void save() {
InvocationHandler.invoke(this,savemethod,args);
}//maybe...
注:利用動態代理要求目標對象必須實現接口,假如目標對象沒有實現接口,則應該用cglib來實現。

17.CGLIB實現攔截:不要求目標對象實現接口,代理對象創建的時候繼承目標對象,並且覆蓋目標對象所有非final的方法,當利用代理對象調用目標對象的方法時,會調用MethodInterceptor.interceptor()方法,在該方法裏面做權限判斷,權限通過時再將方法調用委派給目標對象。

private Object targetObject;

public Object createProxyObject(Object targetObject) {
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.targetObject.getClass());//繼承了目標類,並且覆蓋目標類所有非final的方法
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
UserServiceBean userService = (UserServiceBean)this.targetObject;
Object result = null;
if(userService.getUser() != null) {
result = methodProxy.invoke(targetObject, args);
}
return result;
}

同時因爲代理對象不需要目標對象實現接口,所以要用目標對象類直接飲用代理對象:

UserServiceBean userService = (UserServiceBean)factory.createProxyObject(new UserServiceBean("曾險峯"));
userService.save("Teeny");

18.各種通知:

public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
UserServiceBean userService = (UserServiceBean)this.targetObject;
Object result = null;
//環繞通知
if(userService.getUser() != null) {
//前置通知
try{
result = methodProxy.invoke(targetObject, args);
} catch(Exception e) {
//例外通知
} finally {
//最終通知
}
//後置通知
}
return result;
}

19.AOP概念:
切面(aspect):與類類似,不過類是對物體特徵的抽象,切面是對橫切性關注點的抽象,前面整個的JDKProxyFactory和CGLIBProxyFactory都可以看作是一個切面,是對客戶端與bean之間一層攔截定義的抽象;
連接點(joinpoint):指的是被攔截到的點,在Spring中就是指方法,實際上還可以是域和構造器;
切入點(pointcut):指的是對joinpoint進行攔截的定義;
advice(通知):前有介紹;
目標對象(target);
織入(weave):將aspect應用到target對象並創建代理對象的過程;
引入(introduction):在不修改類得前提下,在運行期爲爲類動態添加一些域和方法

20.Spring進行aop編程:
註解方式:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi: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 />
</beans>

@Aspect @Component//定義切面,並且將bean交給spring管理
public class MyInterceptor {
// "execution (* com.zxf.service..*.*(..))"//
@Pointcut("execution(* spring.aop.service.impl.UserServiceBean.*(..))")
public void anyMethod() {//方法名就是切入點的名稱
}
//定義切入點,括號內的表達式指定對哪些joincut進行攔截
@Before("anyMethod() && args(username)")
public void doAccessCheck(String username){
System.out.println("前置通知");
}
//定義前置通知,指定參數,兩個參數名必須一致,假如被攔截的方法沒有匹配的參數則不會有前置通知,但是可以不與被攔截方法中的參數名一致,但三者類型應一致
@AfterReturning(pointcut=anyMethod()",returning="result")
public void doAfterReturning(String result) {
System.out.println("後置通知" + result);
}
//定義後置通知,並將bean對象方法調用後的結果作爲參數傳入後置通知
@After("anyMethod()")
public void doAfter() {
System.out.println("最終通知");
}

@AfterThrowing(pointcut="anyMethod()",throwing="e")
public void doAfterThrowing(Exception e) {
System.out.println("例外通知" + e.getMessage());
}
//定義例外通知,並將拋出的例外傳給例外通知
@Around("anyMethod()")
public Object doAround(ProceedingJoinPoint pdj) throws Throwable {
Object result = null;
//if(){//權限判斷
System.out.println("環繞通知");
result = pdj.proceed();
//}
return result;
}//定義環繞通知,
}
基於xml方式進行aop編程:
<bean id="myInterceptor" class="spring.aop.service.MyInterceptor2">
</bean>
<bean id="userService" class="spring.aop.service.impl.UserServiceBean2">
</bean>

<aop:config>
<aop:aspect id="myaspect" ref="myInterceptor">
<aop:pointcut id="mycut" expression="execution(* spring.aop.service.impl.UserServiceBean2.*(..))"/>
<aop:before pointcut-ref="mycut" method="doAccessCheck"/>
<aop:after-returning pointcut-ref="mycut" method="doAfterReturning"/>
<aop:after-throwing pointcut-ref="mycut" method="doAfterThrowing"/>
<aop:after pointcut-ref="mycut" method="doAfter"/>
<aop:around pointcut-ref="mycut" method="doAround"/>
</aop:aspect>
</aop:config>
MyInterceptor在這裏只是一個普通的java類,沒有使用任何註解。同時也可以把定義切面的類MyInterceptor和bean都用Spring來管理。名稱爲默認名稱或自己在註解上指定的名稱。
攔截表達式解釋:
java.lang.String spring.aop.service.impl.UserService2.*(java.lang.String , ..)
匹配spring.aop.service.impl.UserService2裏面返回值類型爲String,並且第一個參數類型爲String的方法。
!void spring.aop.service.impl.UserService2.*(java.lang.String , ..)
匹配spring.aop.service.impl.UserService2裏面有返回值,並且第一個參數爲String的方法
* spring.aop..*.*(..)
匹配spring.aop包以及它的子包下面所有類的所有方法。

21.Spring加jdbc集成開發:
基於註解的方式配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi: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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
//讀取配置文件作爲下面datasource的配置
<context:property-placeholder location="classpath:jdbc.properties"/>
//註解方式注入對象
<context:annotation-config/>
//交給Spring自動管理
<context:component-scan base-package="jdbc"/>
//註冊事務管理的處理器
<tx:annotation-driven transaction-manager="txManager"/>
//${}讀取配置文件參數,爲屬性注入值
<bean id="dbConn" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driverClassName}"/>
<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}"/>
<!-- 最大空閒值 -->
<property name="maxIdle" value="${maxIdle}"/>
<property name="minIdle" value="${minIdle}"/>
</bean>

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dbConn"/>
</bean>
</beans>

@Service @Transactional
public class UserServiceBean implements UserService //將bean交給spring 管理同時讓spring來管理事務

注意:這裏讓UserServiceBean實現了UserService接口,所以在getBean的時候不能用

UserServiceBean us = (UserServiceBean)applicationContext.getBean("userServiceBean");//而要用
UserService us = (UserService)applicationContext.getBean("userServiceBean");
//假如不用spring自動管理而是手動配置bean則應該可以解決這個問題。
JUnitTest:
public class Test_006 {

private static UserService us = null;

@BeforeClass
public static void beforClass() {
try {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"beans_5.xml");
us = (UserService) applicationContext.getBean("userServiceBean");
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void getUser(){
System.out.println(us.getUser(1).getName());
}

@Test
public void updateUser() {
UserBean user = (UserBean)us.getUser(1);
user.setName("Teeny");
us.update(user);
}

@Test
public void save() {
UserBean user = new UserBean();
user.setName("曾險峯");
us.save(user);
}

@Test
public void getAllUsers() {
List<UserBean> users = us.getAllUsers();
for(UserBean u : users){
System.out.println(u.getName());
}
}

@Test
public void deleteUser() {
us.delete(1);
}
}

ServiceBean:

@Service @Transactional
public class UserServiceBean implements UserService {

private JdbcTemplate jdbcTemplate;

@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}//setDataSource(DataSource dataSource)在Spring容器中選擇dataSource的bean
public void save(UserBean user) {
this.jdbcTemplate.update("insert into T_Spring(name) values(?)", new Object[]{user.getName()},
new int[]{java.sql.Types.VARCHAR});
}

public void update(UserBean user) {
this.jdbcTemplate.update("update T_Spring set name=? where id=?", new Object[]{user.getName(),user.getId()},
new int[]{java.sql.Types.VARCHAR,java.sql.Types.INTEGER});
}

public UserBean getUser(Integer id) {
UserBean user = new UserBean();
user = (UserBean)this.jdbcTemplate.queryForObject("select * from T_Spring where id=?", new Object[]{id},new UserRowMapper());
return user;
}

public List<UserBean> getAllUsers() {
List<UserBean> users = new ArrayList<UserBean>();
users = (List<UserBean>)this.jdbcTemplate.query("select * from T_Spring", new UserRowMapper());
return users;
}

public void delete(Integer id) {
this.jdbcTemplate.update("delete from T_Spring where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
}
}

利用Spring封裝好的jdbcTemplate進行bean的操作,還須提供一個實現了RowMapper的類,作爲記錄的映射:

public class UserRowMapper implements RowMapper {
public Object mapRow(ResultSet rs, int arg1) throws SQLException {
UserBean user = new UserBean();
user.setName(rs.getString("name"));
user.setId(rs.getInt("id"));
return user;
}
}

22.Spring回滾的情況:

runtimeException--------------------回滾
public void delete(Integer id) {
this.jdbcTemplate.update("delete from T_Spring where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
throw new RuntimeException();
}
不會執行刪除操作。
checkedException--------------------不回滾
public void delete(Integer id) throws Exception {
this.jdbcTemplate.update("delete from T_Spring where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
//throw new RuntimeException();
}
@Test
public void deleteUser() {
try {
us.delete(2);
} catch (Exception e) {
e.printStackTrace();
}
//上面是對checkedException回滾的測試
//us.delete(1);
}//不回滾
這些默認管理行爲可以修改:
@Transactional(RollbackFor=Exception.class)
public void delete(Integer id) throws Exception {
this.jdbcTemplate.update("delete from T_Spring where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
//throw new RuntimeException();
}
在delete方法上指定checkedException也可以回滾
@Transactional(noRollbackFor=RuntimeException.class)
public void delete(Integer id) {
this.jdbcTemplate.update("delete from T_Spring where id=?", new Object[]{id},
new int[]{java.sql.Types.INTEGER});
throw new RuntimeException();
}
指定delete方法上RuntimeException不回滾。
指定有些方法不需要開啓事務管理(只有增刪改才需要):
@Transactional(propagation=Propagation.NOT_SUPPORTED)
public UserBean getUser(Integer id) {
UserBean user = new UserBean();
user = (UserBean)this.jdbcTemplate.queryForObject("select * from T_Spring where id=?", new Object[]{id},new UserRowMapper());
return user;
}
事務傳播屬性:
REQUIRED:該方法需要一個事務,如果方法執行時已經在一個事務當中則加入該事務,夠則創建一個新事務,默認屬性!
NOT_SUPPORTED:不需要事務。當這個方法在其他對象的需要事務支持的方法中執行的時候,原先的事務就會被掛起,等這個不需要事務的方法執行結束後才恢復執行。
REQUIRESNES:不論當前是否有事務開啓,該方法都需要開啓一個新事務,並且會讓其他事務掛起,等方法執行完,新事務結束後原先事務才恢復執行。
MANDATORY:要求方法必須在一個已有的事務中執行,方法本身不能開啓事務,否則會出錯。
SUPPORTS:可以在事務中執行,也可以不在事務中執行。
NEVER:絕對不能在事務中執行。
NESTED:回滾至savepoint。
其他屬性設置:
readOnly:boolean類型,是否爲只讀事務。
isolation:事務隔離級別:(MYSQL默認第三種)
isolation=Isolation.REPEATABLE_READ可重複讀,有幻讀(有記錄插入和刪除的操作)。
isolation=Isolation.SERIALIZABLE串行化,事務無併發,最高級別。


23.基於xml方式配置事務管理:


<tx:annotation-driven transaction-manager="txManager"/> 
<!-- 

定義個切入點,對所有需要事務管理的方法進行攔截,同時把這些攔截到的方法教給一個通知處理器txAdvice處理 

--> 
<aop:config> <aop:pointcut id="transactionPointcut" expression="execution(* jdbc.service..*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut"/> </aop:config>
<!-- 
定義個通知處理器,它的事務管理器爲txManager
--> 
<tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/> <tx:method name="*"/> </tx:attributes> </tx:advice>

已經配置好了,假如事務管理器能夠管理事務,則在下面有問題的delete方法執行的時候,兩個操作都不會提交(否則下面方法中的兩個語句的執行是在兩個事務中執行的): 
//@Transactional(noRollbackFor=Exception.class) 
public void delete(Integer id) throws Exception { 
this.jdbcTemplate.update("delete from T_Spring where id=?", new Object[]{id}, 
new int[]{java.sql.Types.INTEGER}); 
this.jdbcTemplate.update("delete from T_ Springss where id=6");
//throw new RuntimeException(); 
} 
結果兩個刪除都沒有執行,把配置文件註釋掉後,前面語句已經提交,後面的拋出異常。
Spring與Struts2、H ibernate集成待續。。。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章