spring-wd
Spring自己的笔记
1.springIOC
-
在xml中注入bean。
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <bean id="hasParameterBean" class="com.cskaoyan.bean.HasParameterBean"> <constructor-arg name="username" value="songge"/> <constructor-arg name="password" value="niupi"/> </bean> <!--静态工厂--> <!--factory-method属性:类中静态方法 --> <!--组件类型:不是class对应的类型 → factory-method方法的返回值类型--> <bean id="userFromStaticFactory" class="com.cskaoyan.factory.UserStaticFactory" factory-method="create"/> <!--实例工厂--> <bean id="instanceFactory" class="com.cskaoyan.factory.UserInstanceFactory"/> <!--factory-bean 引用容器中的工厂组件--> <!--factory-method factory-bean中的方法名--> <!--组件类型: → factory-method方法的返回值类型--> <bean id="userFromInstanceFactory" factory-bean="instanceFactory" factory-method="create"/> <!--FactoryBean组件类型是和getObject方法的返回值是相关的--> <bean id="userFromFactoryBean" class="com.cskaoyan.factory.UserFactoryBean"/> </beans> -
使用注解的方式注入
<!-- bean definitions here --> <!--base-package指的是com.cskaoyan这个包,及其子包--> <context:component-scan base-package="com.cskaoyan"/>注解的方式赋值:
@Value("songgexxx") // @Value("${userservice.username}") String username; <context:property-placeholder location="classpath:parameter.properties"/> //@Autowired //@Qualifier("userDaoImpl") //@Resource @Resource(name = "userDaoImpl2")//通过@Resource注解的name属性值指定组件id UserDao userDao; //从容器中取出userDao组件给到这个成员变量
2.AOP
aop的几种方式:
方式一:使用代理类ProxyFactoryBean,注意这种方式的目标类,必须有接口实现。
一个通知需要实现MethodInterceptor 接口。具体代码如下
<!-- bean definitions here -->
<context:component-scan base-package="com.cskaoyan"/>
<bean id="helloServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="helloServiceImpl1"/>
<!--interceptorNames接收的是字符串 👉 value属性-->
<property name="interceptorNames" value="customAdvice"/>
</bean>
通知:
@Component
public class CustomAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("正道的光");
Object proceed = methodInvocation.proceed();//执行的是委托类的方法
System.out.println("照在大地上");
return proceed;
}
}
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application.xml")
public class MyTest {
//@Autowired
//@Qualifier("helloServiceProxy")
// @Resource(name = "helloServiceProxy")
// HelloService helloService;
@Autowired
HelloService helloServiceProxy;
@Test
public void mytest1() {
helloServiceProxy.sayHello();
}
}
方式二:
加入依赖aspectjweaver依赖
通知是需要加入一个MethodInterceptor。主要的区别是xml文件中的区别。
有了pointcut了之后,就是通过advisor指定通知,pointcut这种方式可以指定特定的方法,进行指定加强,而不再是像之前那样对这个类的所有方法进行了增强。
<aop:config>
<!--advice-ref:引用容器中的通知组件id-->
<!--pointcut:切入点表达式 → 指定增强方法-->
<!--<aop:advisor advice-ref="customAdvice" pointcut="execution(public void com.cskaoyan.service.HelloServiceImpl.sayHello())"/>-->
<!-- <aop:pointcut id="helloPointcut" expression="execution(public void com.cskaoyan.service.HelloServiceImpl.sayHello())"/>-->
<!-- <aop:advisor advice-ref="customAdvice" pointcut-ref="helloPointcut"/>-->
<!-- <aop:advisor advice-ref="customAdvice" pointcut="execution(public void com.cskaoyan.service.HelloServiceImpl.sayHello())"/>-->
<aop:advisor advice-ref="customAdvice" pointcut="execution(* com..*l.sayHello())"/>
</aop:config>
pointcut的写作方式:
基本格式:execution(修饰符 返回值 包名.类名.方法名(形参))
修饰符是可以省略的,也就是直接不要了。
返回值,如果是javabean的话,写全类名。可以使用*来统配。
报名.类名.方法名(形参)
头尾不能省略,使用..代表中间任意部分。这里的头尾不能省略,那么也就是这个pointcut必须是指向一个特定的类中去了。好像是不可以指向一大片的类。
使用*通配。
"execution(* com..service.*Impl.*(..))"/><!--service层下的任意实现类组件下的任意包含单个参数的方法-->
方式三:方式二的升级版,有返回值,还有异常的返回。
而且是通知不需要实现MethodInterceptor接口了。
依赖:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
通知变成了一个bean
package com.cskaoyan.asepct;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
/**
* 要不通知对应的方法写在组件中
*/
@Component
public class CustomAspect {
/**
* 可以在通知方法的形参上增加一个参数JoinPoint
*/
public void mybefore(JoinPoint joinPoint) {
//Signature signature = joinPoint.getSignature();
//String name = signature.getName();
//System.out.println("马上执行" + name + "方法");
//
//Object[] args = joinPoint.getArgs();
//System.out.println(Arrays.asList(args));
//
//Object target = joinPoint.getTarget();
//Object aThis = joinPoint.getThis();
//System.out.println("target = " + target);
//System.out.println("this = " + aThis);
//
//System.out.println("target class = " + target.getClass().getName());
//System.out.println("this class = " + aThis.getClass().getName());
System.out.println("正道的光");
}
public void myafter(/*JoinPoint joinPoint*/) {
System.out.println("照在大地上");
}
public Object around(ProceedingJoinPoint joinPoint)/* throws Throwable*/ {
System.out.println("around 的before");
Object proceed = null;//类似于method.invoke 、methodInvocation.proceed
try {
proceed = joinPoint.proceed();
} catch (Throwable throwable) {
//throwable.printStackTrace();
System.out.println("try catch住了");
}
System.out.println("around 的after");
return proceed;
}
public void afterReturning(Object returnValue/*,JoinPoint joinPoint*/) {
//String name = joinPoint.getSignature().getName();
System.out.println("方法返回值为 " + returnValue);
}
public void afterThrowing(Exception exception) {
System.out.println("抛出了 " + exception.getClass().getName() + "异常,异常信息是" + exception.getMessage());
}
}
XML需要对应的注入方式
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<context:component-scan base-package="com.cskaoyan"/>
<aop:config>
<aop:pointcut id="customPointcut1" expression="execution(* com..service..*(..))"/>
<aop:aspect ref="customAspect">
<!--<aop:pointcut id="" expression=""/>-->
<aop:before method="mybefore" pointcut="execution(* com..service..*(..))"/>
<aop:before method="mybefore" pointcut-ref="customPointcut1"/>
<aop:after method="myafter" pointcut-ref="customPointcut1"/>
<aop:around method="around" pointcut-ref="customPointcut1"/>
<aop:after-returning method="afterReturning" pointcut-ref="customPointcut1" returning="returnValue"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="customPointcut1" throwing="exception"/>
</aop:aspect>
</aop:config>
</beans>
方式四。就是方式三的注解方式。
依赖。通知如上
需要在xml中加入:
package com.cskaoyan.asepct;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* 要不通知对应的方法写在组件中
*/
@Aspect
@Component
public class CustomAspect {
//需要方法辅助切入点的表达
//修饰符可以为private或public
//返回值为void
//方法名 → pointcut的id
//形参和方法体都为空
//@Pointcut注解的value属性中写的是切入点表达式
@Pointcut("execution(* com..service..*(..))")
public void customPointcut(){}
//@Before("execution(* com..service..*(..))")
@Before("customPointcut()")
public void mybefore(JoinPoint joinPoint){
System.out.println("正道的光");
}
@After("customPointcut()")
public void myafter(/*JoinPoint joinPoint*/){
System.out.println("照在大地上");
}
@Around("customPointcut()")
public Object around(ProceedingJoinPoint joinPoint)/* throws Throwable*/ {
System.out.println("around 的before");
Object proceed = null;//类似于method.invoke 、methodInvocation.proceed
try {
proceed = joinPoint.proceed();
} catch (Throwable throwable) {
//throwable.printStackTrace();
System.out.println("try catch住了");
}
System.out.println("around 的after");
return proceed;
}
@AfterReturning(value = "customPointcut()",returning = "returnValue")
public void afterReturning(Object returnValue/*,JoinPoint joinPoint*/){
//String name = joinPoint.getSignature().getName();
System.out.println("方法返回值为 " + returnValue);
}
@AfterThrowing(value = "customPointcut()",throwing = "exception")
public void afterThrowing(Exception exception){
System.out.println("抛出了 " + exception.getClass().getName() + "异常,异常信息是" + exception.getMessage());
}
}
将目标和通知彻底分开了。通知只是需要指向目标即可,我们在获取目标的时候,是自动增强这些方法的。
方式五,自定义注解的 方式,注解放在那里,就针对性的加强某个方法。
1.注解的自定义
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CountTime {}
2.通知的书写
package com.cskaoyan.asepct;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class CountTimeAspect {
//@Pointcut注解的value属性中写 @annotation(自定义的注解) → 自定义注解出现在什么地方 → 什么地方就要被增强
@Pointcut("@annotation(com.cskaoyan.anno.CountTime)")
public void customPointcut(){}
@Around("customPointcut()")
public Object around(ProceedingJoinPoint joinPoint){
long start = System.currentTimeMillis();
Object proceed = null;
try {
proceed = joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println(joinPoint.getSignature().getName() + "方法的执行时间为" + (end - start));
return proceed;
}
}
目标类
package com.cskaoyan.service;
import com.cskaoyan.anno.CountTime;
import org.springframework.stereotype.Service;
@Service
public class HelloServiceImpl implements HelloService{
@Override
public void sayHello() {
System.out.println("hello world");
}
@CountTime
@Override
public Integer add(Integer a, Integer b) {
//long l = System.currentTimeMillis();
int x = a + b;
System.out.println("a + b的结果为" + x);
//int i = 1/0;
//long l1 = System.currentTimeMillis();
//Thread.sleep(500);
return x;
}
}
3.Spring-TX
中间是学习了jdbcTemplate了。这个bean,主要是依赖了,DruidDataSource,使用的时候,直接取出来用就好了。
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/j24_db?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
使用的时候,是直接取出来使用。
package com.cskaoyan.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class AccountDaoImpl implements AccountDao{
@Autowired
JdbcTemplate jdbcTemplate;
@Override
public Integer selectMoneyById(Integer id) {
Integer integer = jdbcTemplate.queryForObject("select money from j24_account_t where id = ?", Integer.class, id);
return integer;
}
@Override
public int update(Integer id, Integer money) {
int update = jdbcTemplate.update("update j24_account_t set money = ? where id = ?", money, id);
return update;
}
}
方式一:Spring-Transaction-template
需要在容器中注入bean。TransactionTemplate,这个bean需要依赖DataSourceTransactionManager
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<context:component-scan base-package="com.cskaoyan"/>
<!--application.xml-->
<!--application-xxx.xml-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/j24_db?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
</beans>
service层:
package com.cskaoyan.service;
import com.cskaoyan.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Service
public class AccountServiceImpl implements AccountService{
@Autowired
TransactionTemplate transactionTemplate;
@Autowired
AccountDao accountDao;
@Override
public void transfer(Integer fromId, Integer destId, Integer money) {
Integer fromMoney = accountDao.selectMoneyById(fromId) - money;
Integer destMoney = accountDao.selectMoneyById(destId) + money;
Integer execute = transactionTemplate.execute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus transactionStatus) {
accountDao.update(fromId, fromMoney);
//int i = 1 / 0;
accountDao.update(destId, destMoney);
System.out.println(destMoney);
return destMoney;
}
});//execute方法的返回值就是接收DoInTransaction方法的返回值
System.out.println(execute);
}
@Override
public void transfer2(Integer fromId, Integer destId, Integer money) {
Integer fromMoney = accountDao.selectMoneyById(fromId) - money;
Integer destMoney = accountDao.selectMoneyById(destId) + money;
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.update(fromId, fromMoney);
int i = 1 / 0;
accountDao.update(destId, destMoney);
}
});
}
}
方式二:transaction-proxy,指定了target。和transactionManager。
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<context:component-scan base-package="com.cskaoyan"/>
<!--application.xml-->
<!--application-xxx.xml-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/j24_db?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--target-->
<property name="target" ref="accountServiceImpl"/>
<!--transactionManager-->
<property name="transactionManager" ref="transactionManager"/>
<!--transactionAttributes → Definition-->
<property name="transactionAttributes">
<props>
<!--key方法名-->
<!--
隔离级别:ISOLATION_XXX → ISOLATION_REPEATABLE_READ、ISOLATION_DEFAULT
传播行为:PROPAGATION_XXX → PROPAGATION_REQUIRED、PROPAGATION_NESTED
超时:timeout_数字 单位是秒
只读:readOnly
-XXXException:rollBackFor
+xxxException:noRollBackFor
-->
<prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
</props>
</property>
</bean>
</beans>
目标代码:
package com.cskaoyan.dao;
public interface AccountDao {
public Integer selectMoneyById(Integer id);
public int update(Integer id, Integer money);
}
package com.cskaoyan.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import javax.sql.DataSource;
@Repository
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
@Autowired
public void setSuperDatasource(@Qualifier("dataSource") DataSource datasource){
super.setDataSource(datasource);
}
//@Autowired
//JdbcTemplate jdbcTemplate;
@Override
public Integer selectMoneyById(Integer id) {
Integer integer = getJdbcTemplate().queryForObject("select money from j24_account_t where id = ?", Integer.class, id);
return integer;
}
@Override
public int update(Integer id, Integer money) {
int update = getJdbcTemplate().update("update j24_account_t set money = ? where id = ?", money, id);
return update;
}
}
package com.cskaoyan.service;
public interface AccountService {
void transfer(Integer fromId,Integer destId,Integer money);
}
package com.cskaoyan.service;
import com.cskaoyan.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AccountServiceImpl implements AccountService{
@Autowired
AccountDao accountDao;
@Override
public void transfer(Integer fromId, Integer destId, Integer money) {
Integer fromMoney = accountDao.selectMoneyById(fromId) - money;
Integer destMoney = accountDao.selectMoneyById(destId) + money;
accountDao.update(fromId, fromMoney);
int i = 1/0;
accountDao.update(destId, destMoney);
}
}
测试代码:
package com.cskaoyan;
import com.cskaoyan.dao.AccountDao;
import com.cskaoyan.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application.xml")
public class SpringTest {
@Autowired
@Qualifier("accountServiceProxy")
AccountService accountService;
@Test
public void mytest3(){
accountService.transfer(1,2,100);
}
}
方式三:使用aop中的advisor
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<context:component-scan base-package="com.cskaoyan"/>
<!--application.xml-->
<!--application-xxx.xml-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/j24_db?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com..service..*(..))"/>
</aop:config>
<!--tx提供了通知 👉 tx标签-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--name属性对应的是方法名-->
<!--其他属性和definition相关-->
<tx:method name="transfer*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
</beans>
其他的不变。
方式四:注解的方式,最简单。
依赖:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
配置文件:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<context:component-scan base-package="com.cskaoyan"/>
<!--application.xml-->
<!--application-xxx.xml-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/j24_db?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务注解开关-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
使用过程:
package com.cskaoyan.service;
import com.cskaoyan.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional//写在类上,意味着当前类(容器中的组件)的全部方法都增加事务
public class AccountServiceImpl implements AccountService{
@Autowired
AccountDao accountDao;
//transactional注解中包含属性 👉 definition
//@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly = true)
//@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,timeout = 5)
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,noRollbackFor = ArithmeticException.class)
@Override
public void transfer(Integer fromId, Integer destId, Integer money) {
Integer fromMoney = accountDao.selectMoneyById(fromId) - money;
Integer destMoney = accountDao.selectMoneyById(destId) + money;
accountDao.update(fromId, fromMoney);
int i = 1 / 0;
accountDao.update(destId, destMoney);
}
}
-
javaconfig的模式。
package com.cskaoyan.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.*; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @Configuration//组件注册可以写在配置类中,配置类本身也是容器中的组件 @ComponentScan("com.cskaoyan") @PropertySource(value = "classpath:db.properties") @EnableAspectJAutoProxy @EnableTransactionManagement public class ApplicationConfiguration { /** * @Bean:注解的value属性可以指定id * 修饰符:public * 返回值:组件对应的class或其接口 * 方法名:如果没有指定组件id,默认以方法名作为组件id * 形参:会从容器中取出该类型的组件,如果该类型组件不止一个,可以使用@Qualifier指定组件id * 方法体:获得一个组件对应的实例就可以了 */ //@Bean @Bean("datasource") //public DruidDataSource dataSource(){} public DataSource dataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/j24_db?useUnicode=true&characterEncoding=utf-8"); dataSource.setUsername("root"); dataSource.setPassword("123456"); return dataSource; } @Bean public JdbcTemplate jdbcTemplate(@Qualifier("datasource") DataSource dataSource){ JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); return jdbcTemplate; } @Bean public DataSourceTransactionManager transactionManager(DataSource dataSource){ DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource); return transactionManager; } }
浙公网安备 33010602011771号