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集成待续。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值