Spring使用AOP來完成聲明式的事務管理 有annotation和xml兩種形式java
代碼和上一篇基本相近,再貼一遍spring
兩個實體類sql
package com.ouc.wkp.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity(name = "t_log") public class Log { private int id; private String msg; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
package com.ouc.wkp.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity(name="user2") public class User2 { private int id; private String username; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } @Column public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
兩個接口DAOexpress
package com.ouc.wkp.dao; import com.ouc.wkp.model.Log; public interface LogDAO { public void save(Log log); }
package com.ouc.wkp.dao; import com.ouc.wkp.model.User2; public interface UserDAO { public void save(User2 user2); public void delete(); }
接口實現apache
package com.ouc.wkp.dao.impl; import java.sql.Connection; import java.sql.SQLException; import javax.annotation.Resource; import javax.sql.DataSource; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.stereotype.Component; import com.ouc.wkp.dao.UserDAO; import com.ouc.wkp.model.User2; @Component("u") public class UserDAOImpl implements UserDAO { // private DataSource dataSource; // // public DataSource getDataSource() { // return dataSource; // } // // @Resource // public void setDataSource(DataSource dataSource) { // this.dataSource = dataSource; // } private SessionFactory sessionFactory; public SessionFactory getSessionFactory() { return sessionFactory; } @Resource public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Override public void save(User2 user2) { // Hibernate // JDBC // XML // NetWork // System.out // .println("session factory class:" + sessionFactory.getClass()); Session s = sessionFactory.getCurrentSession(); // s.beginTransaction(); s.save(user2); // s.getTransaction().commit(); // System.out.println("user saved!"); } @Override public void delete() { // TODO Auto-generated method stub } }
package com.ouc.wkp.dao.impl; import javax.annotation.Resource; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.stereotype.Component; import com.ouc.wkp.dao.LogDAO; import com.ouc.wkp.model.Log; @Component("logDAO") public class LogDAOImpl implements LogDAO { private SessionFactory sessionFactory; public SessionFactory getSessionFactory() { return sessionFactory; } @Resource public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Override public void save(Log log) { Session s = sessionFactory.getCurrentSession(); s.save(log); // throw new RuntimeException();//事務會回滾 spring配置後省去了try catch } }
package com.ouc.wkp.service; import javax.annotation.Resource; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.ouc.wkp.dao.LogDAO; import com.ouc.wkp.dao.UserDAO; import com.ouc.wkp.model.Log; import com.ouc.wkp.model.User2; @Component("userService") public class UserService { private UserDAO userDAO; private LogDAO logDAO; public LogDAO getLogDAO() { return logDAO; } @Resource(name = "logDAO") public void setLogDAO(LogDAO logDAO) { this.logDAO = logDAO; } public User2 getUser(int id) { return null; } public void init() { System.out.println("init"); } // @Transactional(propagation = Propagation.REQUIRED) // 事務的傳播特性 默認REQUIRED // readOnly=true只讀的 spring會進行優化 // 聲明式事務管理 進行事務 public void add(User2 user2) { userDAO.save(user2); Log log = new Log(); log.setMsg("a user saved"); logDAO.save(log); } public UserDAO getUserDAO() { return userDAO; } @Resource(name = "u") public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } public void destroy() { System.out.println("destroy"); } }
使用註解時在對應的方法前加上@Transactional(propagation = Propagation.REQUIRED)session
(propagation = Propagation.REQUIRED)能夠省去,由於事務的傳播特性 默認爲REQUIREDide
配置文件測試
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context-3.1.xsd 9 http://www.springframework.org/schema/aop 10 http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 11 http://www.springframework.org/schema/tx 12 http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> 13 <context:annotation-config /> 14 <!-- 使用註解須要下面四條 --> 15 <!-- xmlns:context="http://www.springframework.org/schema/context" --> 16 <!-- http://www.springframework.org/schema/context --> 17 <!-- http://www.springframework.org/schema/context/spring-context-3.1.xsd"> --> 18 <!-- <context:annotation-config /> --> 19 20 <!-- 使用aop須要一下 --> 21 <!-- xmlns:aop="http://www.springframework.org/schema/aop" --> 22 <!-- http://www.springframework.org/schema/aop --> 23 <!-- http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> --> 24 <!-- <aop:aspectj-autoproxy /> --> 25 26 <!-- 使用事務 --> 27 <!-- xmlns:tx="http://www.springframework.org/schema/tx" --> 28 <!-- http://www.springframework.org/schema/tx --> 29 <!-- http://www.springframework.org/schema/tx/spring-tx-2.5.xsd --> 30 <!-- <tx:annotation-driven transaction-manager="txManager"/> --> 31 32 33 <!-- 掃描 --> 34 <context:component-scan base-package="com.ouc.wkp"></context:component-scan> 35 36 <aop:aspectj-autoproxy /> 37 38 <bean 39 class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 40 <property name="locations"> 41 <value>classpath:jdbc.properties</value> 42 </property> 43 </bean> 44 45 <bean id="dataSource" destroy-method="close" 46 class="org.apache.commons.dbcp.BasicDataSource"> 47 <property name="driverClassName" value="${jdbc.driverClassName}" /> 48 <property name="url" value="${jdbc.url}" /> 49 <property name="username" value="${jdbc.username}" /> 50 <property name="password" value="${jdbc.password}" /> 51 </bean> 52 53 <bean id="sessionFactory" 54 class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 55 <property name="dataSource" ref="dataSource" /> 56 <!-- <property name="annotatedClasses"> --> 57 <!-- <list> --> 58 <!-- <value>com.ouc.wkp.model.User2</value> --> 59 <!-- <value>com.ouc.wkp.model.Log</value> --> 60 <!-- </list> --> 61 <!-- </property> --> 62 <property name="packagesToScan"> 63 <list> 64 <value>com.ouc.wkp.model</value> 65 </list> 66 </property> 67 <property name="hibernateProperties"> 68 <props> 69 <prop key="hibernate.dialect"> 70 org.hibernate.dialect.MySQLDialect 71 </prop> 72 <prop key="hibernate.show_sql">true</prop> 73 </props> 74 </property> 75 </bean> 76 77 78 <!-- Spring使用AOP來完成聲明式的事務管理 --> 79 <bean id="txManager" 80 class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 81 <!-- <property name="dataSource" ref="dataSource" /> --> 82 <property name="sessionFactory" ref="sessionFactory" /> 83 </bean> 84 85 <tx:annotation-driven transaction-manager="txManager" /> 86 87 <aop:config> 88 <aop:pointcut expression="execution(public * com.ouc.wkp.service..*.*(..))" 89 id="businessService" /> 90 <!-- 在此pointcut上加上txAdvice建議 --> 91 <aop:advisor advice-ref="txAdvice" pointcut-ref="businessService" /> 92 </aop:config> 93 94 <tx:advice id="txAdvice" transaction-manager="txManager"> 95 <tx:attributes> 96 <tx:method name="getUser" read-only="true" /> 97 <tx:method name="add*" propagation="REQUIRED" /> 98 </tx:attributes> 99 </tx:advice> 100 101 </beans>
兩個地方須要注意優化
1.這種方式能夠省去寫多個model類的配置this
<property name="packagesToScan">
<list>
<value>com.ouc.wkp.model</value>
</list>
</property>
2.
bean定義了一個事務管理,注入sessionFactory。
緊接着規定事務管理器爲txManager即上面bean中定義的。
<aop:config>定義一個切面,在這個切面加上advice。
最後定義一個advice,
<tx:method name="getUser" read-only="true" />表示getUser方法是隻讀的而且進行了聲明式事務管理。readonly能夠提升程序效率。
<tx:method name="add*" propagation="REQUIRED" />標識爲以add開頭的方法添加事務。
測試類
package com.ouc.wkp.test; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.ouc.wkp.model.User2; import com.ouc.wkp.service.UserService; //Dependency Injection //Inverse of Control public class UserServiceTest { @Test public void testAdd() throws Exception { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( "beans.xml"); UserService service = (UserService) ctx.getBean("userService"); User2 user2=new User2(); user2.setId(1); user2.setUsername("ttyy"); System.out.println(user2); service.add(user2); ctx.destroy(); } }
若是出錯則事務回滾,兩條記錄都增長失敗。