Spring笔记
1.基于XML的配置
1.1 pom文件
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency>
1.2 创建配置文件并导入头
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
1.3在配置文件中配置类
<!---配置service --> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> </bean> <!-- 配置dao --> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
1.4测试SpringBoot环境是否搭配完成
public static void main(String[] args) { //1.使用ApplicationContext接口,就是在获取spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //2.根据bean的id获取对象 IAccountService aService = (IAccountService) ac.getBean("accountService"); System.out.println(aService); IAccountDao aDao = (IAccountDao) ac.getBean("accountDao"); System.out.println(aDao); }
1.5一些细节
1 BeanFactory 和ApplicationContext 的区别

2 ApplicationContext 接口的实现类

1.6 bean标签

1.7 SpringIOC的注入
public class AccountServiceImpl implements IAccountService { private String name; private Integer age; private Date birthday;
public AccountServiceImpl(String name, Integer age, Date birthday) { this.name = name; this.age = age; this.birthday = birthday; } @Override public void saveAccount() { System.out.println(name+","+age+","+birthday); } }
<!-- 使用构造函数的方式,给 service 中的属性传值 要求: 类中需要提供一个对应参数列表的构造函数。 涉及的标签: constructor-arg 属性: index:指定参数在构造函数参数列表的索引位置 type:指定参数在构造函数中的数据类型 name:指定参数在构造函数中的名称 用这个找给谁赋值 =======上面三个都是找给谁赋值,下面两个指的是赋什么值的============== value:它能赋的值是基本数据类型和 String 类型 ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean --> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <constructor-arg name="name" value="张三"></constructor-arg> <constructor-arg name="age" value="18"></constructor-arg> <constructor-arg name="birthday" ref="now"></constructor-arg> </bean> <bean id="now" class="java.util.Date"></bean>
1.8.set方式注入
public class AccountServiceImpl implements IAccountService { private String name; private Integer age; private Date birthday;
public void setName(String name) { this.name = name; } public void setAge(Integer age) { this.age = age; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public void saveAccount() { System.out.println(name+","+age+","+birthday); } }
<!--通过配置文件给 bean 中的属性传值:使用 set 方法的方式 涉及的标签: property 属性: name:找的是类中 set 方法后面的部分 ref:给属性赋值是其他 bean 类型的 value:给属性赋值是基本数据类型和 string 类型的 实际开发中,此种方式用的较多。 --> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <property name="name" value="test"></property> <property name="age" value="21"></property> <property name="birthday" ref="now"></property> </bean> <bean id="now" class="java.util.Date"></bean>
1.9注入集合属性
public class AccountServiceImpl implements IAccountService { private String[] myStrs; private List<String> myList; private Set<String> mySet; private Map<String,String> myMap; private Properties myProps;
public void setMyStrs(String[] myStrs) { this.myStrs = myStrs; } public void setMyList(List<String> myList) { this.myList = myList; } public void setMySet(Set<String> mySet) { this.mySet = mySet; } public void setMyMap(Map<String, String> myMap) { this.myMap = myMap; } public void setMyProps(Properties myProps) { this.myProps = myProps; } @Override public void saveAccount() { System.out.println(Arrays.toString(myStrs)); System.out.println(myList); System.out.println(mySet); System.out.println(myMap); System.out.println(myProps); } }
<!-- 注入集合数据 List 结构的: array,list,set Map 结构的 map,entry,props,prop --> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <!-- 在注入集合数据时,只要结构相同,标签可以互换 --> <!-- 给数组注入数据 --> <property name="myStrs"> <set> <value>AAA</value> <value>BBB</value> <value>CCC</value> </set> </property> <!-- 注入 list 集合数据 --> <property name="myList"> <array> <value>AAA</value> <value>BBB</value> <value>CCC</value> </array> </property> <!-- 注入 set 集合数据 --> <property name="mySet"> <list> <value>AAA</value> <value>BBB</value> <value>CCC</value> </list> </property> <!-- 注入 Map 数据 --> <property name="myMap"> <props> <prop key="testA">aaa</prop> <prop key="testB">bbb</prop> </props> </property> <!-- 注入 properties 数据 --> <property name="myProps"> <map> <entry key="testA" value="aaa"></entry> <entry key="testB"> <value>bbb</value> </entry> </map> </property> </bean>
2. Spring AOP笔记
2.1 使用JDK官方的Proxy代理增强解决数据库事务问题
public class BeanFactory { final TransactionManager txManager = new TransactionManager(); public static IAccountService getAccountService() throws IllegalAccessException, InstantiationException { //1.定义被代理对象 final IAccountService accountService = new AccountServiceImpl(); //2.创建代理对象 IAccountService proxyAccountService = (IAccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(),new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object rtValue = null; try { //开启事务 TransactionManager.beginTransaction(); //执行业务层方法 rtValue = method.invoke(accountService, args); //提交事务 TransactionManager.commit(); }catch(Exception e) { //回滚事务 TransactionManager.rollback(); e.printStackTrace(); }finally { //释放资源 TransactionManager.release(); } return rtValue; } }); return proxyAccountService; } }
2.2 基于XML的AOP开发(DUUtils开发)
1 事前准备:
(1)创建连接数据库工具类
/** * 连接的工具类,它用于从数据源中获取一个连接,并且实现和线程的绑定 */ public class ConnectionUtils { private ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } /** * 获取当前线程上的连接 * @return */ public Connection getThreadConnection() { try{ //1.先从ThreadLocal上获取 Connection conn = tl.get(); //2.判断当前线程上是否有连接 if (conn == null) { //3.从数据源中获取一个连接,并且存入ThreadLocal中 conn = dataSource.getConnection(); tl.set(conn); } //4.返回当前线程上的连接 return conn; }catch (Exception e){ throw new RuntimeException(e); } } /** * 把连接和线程解绑 */ public void removeConnection(){ tl.remove(); } }
(2)JDBCProperties文件
jdbc.driverClass=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/account?useUnicode=true&characterEncoding=utf8 jdbc.username=root jdbc.password=
2.实体类
create table account( id int primary key auto_increment, name varchar(40), money float )character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000); insert into account(name,money) values('ccc',1000); public class Account implements Serializable { private Integer id; private String name; private Float money; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Float getMoney() { return money; } public void setMoney(Float money) { this.money = money; } @Override public String toString() { return "Account{" + "id=" + id + ", name='" + name + '\'' + ", money=" + money + '}'; } }
3. dao层
public interface IAccountDao { /** * 查询所有 * @return */ List<Account> findAllAccount(); /** * 查询一个 * @return */ Account findAccountById(Integer accountId); /** * 保存 * @param account */ void saveAccount(Account account); /** * 更新 * @param account */ void updateAccount(Account account); /** * 删除 * @param acccountId */ void deleteAccount(Integer acccountId); /** * 根据名称查询账户 * @param accountName * @return 如果有唯一的一个结果就返回,如果没有结果就返回null * 如果结果集超过一个就抛异常 */ Account findAccountByName(String accountName); } /** * 账户的持久层实现类 */ public class AccountDaoImpl implements IAccountDao { private QueryRunner runner; private ConnectionUtils connectionUtils; public void setRunner(QueryRunner runner) { this.runner = runner; } public void setConnectionUtils(ConnectionUtils connectionUtils) { this.connectionUtils = connectionUtils; } public List<Account> findAllAccount() { try { return runner.query(connectionUtils.getThreadConnection(),"select * from account",
new BeanListHandler<Account>(Account.class)); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountById(Integer accountId) { try { return runner.query(connectionUtils.getThreadConnection(), "select * from account where id = ?",
new BeanHandler<Account>(Account.class), accountId); } catch (Exception e) { throw new RuntimeException(e); } } public void saveAccount(Account account) { try { runner.update(connectionUtils.getThreadConnection(), "insert into account(name,money) values(?,?)",
account.getName(),account.getMoney()); } catch (Exception e) { throw new RuntimeException(e); } } public void updateAccount(Account account) { try { runner.update(connectionUtils.getThreadConnection(), "update account set name = ?,money = ? where id = ?",
account.getName(),account.getMoney(),account.getId()); } catch (Exception e) { throw new RuntimeException(e); } } public void deleteAccount(Integer acccountId) { try { runner.update(connectionUtils.getThreadConnection(), "delete from account where id = ?",acccountId); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountByName(String accountName) { try{ List<Account> accounts = runner.query(connectionUtils.getThreadConnection(),"select * from account where name = ? ",
new BeanListHandler<Account>(Account.class),accountName); if(accounts == null || accounts.size() == 0){ return null; } if(accounts.size() > 1){ throw new RuntimeException("结果集不唯一,数据有问题"); } return accounts.get(0); }catch (Exception e) { throw new RuntimeException(e); } } }
4.Service层
/** * 账户的业务层接口 */ public interface IAccountService { /** * 查询所有 * @return */ List<Account> findAllAccount(); /** * 查询一个 * @return */ Account findAccountById(Integer accountId); /** * 保存 * @param account */ void saveAccount(Account account); /** * 更新 * @param account */ void updateAccount(Account account); /** * 删除 * @param acccountId */ void deleteAccount(Integer acccountId); /** * 转账 * @param sourceName 转出账户名称 * @param targetName 转入账户名称 * @param money 转账金额 */ void transfer(String sourceName, String targetName, Float money); //void test();//它只是连接点,但不是切入点,因为没有被增强 } /** * 账户的业务层实现类 * 事务控制应该都是在业务层 */ public class AccountServiceImpl2 implements IAccountService{ private IAccountDao accountDao; public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } public List<Account> findAllAccount() { List<Account> accounts = accountDao.findAllAccount(); return accounts; } public Account findAccountById(Integer accountId) { Account account = accountDao.findAccountById(accountId); return account; } public void saveAccount(Account account) { accountDao.saveAccount(account); } public void updateAccount(Account account) { accountDao.updateAccount(account); } public void deleteAccount(Integer acccountId) { accountDao.deleteAccount(acccountId); } public void transfer(String sourceName, String targetName, Float money) { //2.1根据名称查询转出账户 Account source = accountDao.findAccountByName(sourceName); //2.2根据名称查询转入账户 Account target = accountDao.findAccountByName(targetName); //2.3转出账户减钱 source.setMoney(source.getMoney()-money); //2.4转入账户加钱 target.setMoney(target.getMoney()+money); //2.5更新转出账户 accountDao.updateAccount(source); int i=1/0; //2.6更新转入账户 accountDao.updateAccount(target); } }
5.配置事务管理器
public class TransactionManager { private ConnectionUtils connectionUtils; public void setConnectionUtils(ConnectionUtils connectionUtils) { this.connectionUtils = connectionUtils; } /** * 开启事务 */ public void beginTransaction(){ try { connectionUtils.getThreadConnection().setAutoCommit(false); }catch (Exception e){ e.printStackTrace(); } } /** * 提交事务 */ public void commit(){ try { connectionUtils.getThreadConnection().commit(); }catch (Exception e){ e.printStackTrace(); } } /** * 回滚事务 */ public void rollback(){ try { connectionUtils.getThreadConnection().rollback(); }catch (Exception e){ e.printStackTrace(); } } /** * 释放连接 */ public void release(){ try { connectionUtils.getThreadConnection().close();//还回连接池中 connectionUtils.removeConnection(); }catch (Exception e){ e.printStackTrace(); } } public Object transactionAround(ProceedingJoinPoint pip){ Object reValue = null; try { Object[] args = pip.getArgs(); beginTransaction(); //执行方法 reValue = pip.proceed(args); System.out.println(reValue+"----------------------------------"); commit(); }catch (Throwable e){ rollback(); e.printStackTrace(); }finally { release(); } return reValue; } }
5.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置Service --> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <!-- 注入dao --> <property name="accountDao" ref="accountDao"></property> <property name="txManager" ref="txManager"></property> </bean> <bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl2"> <property name="accountDao" ref="accountDao"></property> </bean> <!--配置Dao对象--> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"> <property name="runner" ref="runner"></property> <property name="connectionUtils" ref="connectionUtils"></property> </bean> <!--配置QueryRunner--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"/> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--连接数据库的必备信息--> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 配置Connection的工具类 ConnectionUtils --> <bean id="connectionUtils" class="com.itheima.utils.ConnectionUtils"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置事务管理器--> <bean id="txManager" class="com.itheima.utils.TransactionManager"> <!-- 注入ConnectionUtils --> <property name="connectionUtils" ref="connectionUtils"/> </bean> <!--作用:用于声明开始aop的配置--> <aop:config> <aop:aspect id="txAdvice" ref="txManager"> <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/> <aop:before method="beginTransaction" pointcut-ref="pt1"></aop:before> <aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning> <aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing> <aop:after method="release" pointcut-ref="pt1"></aop:after> <aop:around method="transactionAround" pointcut-ref="pt1"></aop:around> </aop:aspect> </aop:config> </beans>
6.测试类
public class AccountTransactionTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); IAccountService accountService = (IAccountService)context.getBean("accountService"); accountService.transfer("aaa","bbb",100f); } }
2.3 基于注解的AOP开发(DUUtils作为持久层开发)
在Dao层接口的实现中加入 @Repository("accountDao")
在Service层接口实现在中加入@Service("accountService")
1.配置文件
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.itheima"/> <!--配置QueryRunner--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"/> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--连接数据库的必备信息--> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 配置Connection的工具类 ConnectionUtils --> <bean id="connectionUtils" class="com.itheima.utils.ConnectionUtils"> <property name="dataSource" ref="dataSource"></property> </bean> <!--开启aop注解开发--> <aop:aspectj-autoproxy/> </beans>
2.事务管理器类
/** * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接 */ //@Component("txManager") //@Aspect public class TransactionManager2 { @Autowired private ConnectionUtils connectionUtils; @Pointcut("execution(* com.itheima.service.impl.*.*(..))") public void pd1(){ } /** * 开启事务 */ // @Before("pd1()") public void beginTransaction(){ try { connectionUtils.getThreadConnection().setAutoCommit(false); }catch (Exception e){ e.printStackTrace(); } } /** * 提交事务 */ //@AfterReturning("pd1()") public void commit(){ try { connectionUtils.getThreadConnection().commit(); }catch (Exception e){ e.printStackTrace(); } } /** * 回滚事务 */ //@AfterThrowing("pd1()") public void rollback(){ try { connectionUtils.getThreadConnection().rollback(); }catch (Exception e){ e.printStackTrace(); } } /** * 释放连接 */ // @After("pd1()") public void release(){ try { connectionUtils.getThreadConnection().close();//还回连接池中 connectionUtils.removeConnection(); }catch (Exception e){ e.printStackTrace(); } } @Around("pd1()") public Object transactionAround(ProceedingJoinPoint pip){ Object reValue = null; try { Object[] args = pip.getArgs(); beginTransaction(); //执行方法 reValue = pip.proceed(args); System.out.println(reValue+"----------------------------------"); commit(); }catch (Throwable e){ rollback(); e.printStackTrace(); }finally { release(); } return reValue; } }
3.测试类
public class AccountTransactionTest {
@Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml"); IAccountService accountService = (IAccountService)context.getBean("accountService"); accountService.transfer("aaa","bbb",100f); } }
3. SpringTemplate与声明式事务
3.1配置文件的开发
1.持久层的编写
/** * 账户的持久层实现类 */ public class AccountDaoImpl3 implements IAccountDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public List<Account> findAllAccount() { try { return jdbcTemplate.query("select * from account",new BeanPropertyRowMapper<Account>(Account.class)); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountById(Integer accountId) { try { List<Account> list = jdbcTemplate.query("select * from account where id = ?",
new BeanPropertyRowMapper<Account>(Account.class), accountId); return list.isEmpty()?null:list.get(0); } catch (Exception e) { throw new RuntimeException(e); } } public void saveAccount(Account account) { try { jdbcTemplate.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney()); } catch (Exception e) { throw new RuntimeException(e); } } public void updateAccount(Account account) { try { jdbcTemplate.update("update account set name = ?,money = ? where id = ?",account.getName(),account.getMoney(),
account.getId()); } catch (Exception e) { throw new RuntimeException(e); } } public void deleteAccount(Integer acccountId) { try { jdbcTemplate.update("delete from account where id = ?",acccountId); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountByName(String accountName) { try{ List<Account> accounts = jdbcTemplate.query("select * from account where name = ? ",
new BeanPropertyRowMapper<Account>(Account.class),accountName); if(accounts == null || accounts.size() == 0){ return null; } if(accounts.size() > 1){ throw new RuntimeException("结果集不唯一,数据有问题"); } return accounts.get(0); }catch (Exception e) { throw new RuntimeException(e); } } }
2.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: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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置Service --> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl2"> <property name="accountDao" ref="accountDao"></property> </bean> <!--配置Dao对象--> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl3"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!-- 配置一个数据库的操作模板:JdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--连接数据库的必备信息--> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 配置一个事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 事务的配置 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" read-only="false" propagation="REQUIRED"/> <tx:method name="find*" read-only="true" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <!--aop配置--> <aop:config> <aop:pointcut id="pd1" expression="execution(* com.itheima.service.impl.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pd1"/> </aop:config> </beans>
3.测试类
public class AccountTransactionTest { @Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("jdbcTemplate.xml"); IAccountService accountService = (IAccountService)context.getBean("accountService"); accountService.transfer("aaa","bbb",100f); } }
3.2纯注解开发
1.配置文件类
@Configuration @EnableTransactionManagement @ComponentScan(basePackages = "com.itheima") @PropertySource("classpath:jdbc.properties") public class SpringTxConfiguration { @Value("${jdbc.driverClass}") public String driver; @Value("${jdbc.url}") public String url; @Value("${jdbc.username}") public String username; @Value("${jdbc.password}") public String password; @Bean(name="dataSource") public DataSource createDataSource(){ ComboPooledDataSource dataSource = new ComboPooledDataSource(); try { System.out.println(driver); System.out.println(url); System.out.println(password); System.out.println(username); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setPassword(password); dataSource.setUser(username); } catch (PropertyVetoException e) { e.printStackTrace(); } return dataSource; } @Bean(name="jdbcTemplate") public JdbcTemplate createJdbcTemplate(DataSource dataSource){ return new JdbcTemplate(dataSource); } @Bean(name="transactionManager") public DataSourceTransactionManager createtransactionManager(DataSource dataSource){ return new DataSourceTransactionManager(dataSource); } }
2.持久层类
/** * 账户的持久层实现类 */ @Repository("accountDao") public class AccountDaoImpl3_Anno implements IAccountDao { @Autowired private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public List<Account> findAllAccount() { try { return jdbcTemplate.query("select * from account",new BeanPropertyRowMapper<Account>(Account.class)); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountById(Integer accountId) { try { List<Account> list = jdbcTemplate.query("select * from account where id = ?",
new BeanPropertyRowMapper<Account>(Account.class), accountId); return list.isEmpty()?null:list.get(0); } catch (Exception e) { throw new RuntimeException(e); } } public void saveAccount(Account account) { try { jdbcTemplate.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney()); } catch (Exception e) { throw new RuntimeException(e); } } public void updateAccount(Account account) { try { jdbcTemplate.update("update account set name = ?,money = ? where id = ?",
account.getName(),account.getMoney(),account.getId()); } catch (Exception e) { throw new RuntimeException(e); } } public void deleteAccount(Integer acccountId) { try { jdbcTemplate.update("delete from account where id = ?",acccountId); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountByName(String accountName) { try{ List<Account> accounts = jdbcTemplate.query("select * from account where name = ? ",
new BeanPropertyRowMapper<Account>(Account.class),accountName); if(accounts == null || accounts.size() == 0){ return null; } if(accounts.size() > 1){ throw new RuntimeException("结果集不唯一,数据有问题"); } return accounts.get(0); }catch (Exception e) { throw new RuntimeException(e); } } }
3.服务层类
@Service("accountService")
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class AccountServiceImpl2_Anno implements IAccountService{
@Autowired
private IAccountDao accountDao;
public List<Account> findAllAccount() {
List<Account> accounts = accountDao.findAllAccount();
return accounts;
}
public Account findAccountById(Integer accountId) {
Account account = accountDao.findAccountById(accountId);
return account;
}
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(Integer acccountId) {
accountDao.deleteAccount(acccountId);
}
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public void transfer(String sourceName, String targetName, Float money) {
//2.1根据名称查询转出账户
Account source = accountDao.findAccountByName(sourceName);
//2.2根据名称查询转入账户
Account target = accountDao.findAccountByName(targetName);
//2.3转出账户减钱
source.setMoney(source.getMoney()-money);
//2.4转入账户加钱
target.setMoney(target.getMoney()+money);
//2.5更新转出账户
accountDao.updateAccount(source);
// int i=1/0;
//2.6更新转入账户
accountDao.updateAccount(target);
}
}
4.测试类
public class AccountTransactionTest {
@Test public void test3Anno(){ ApplicationContext context = new AnnotationConfigApplicationContext(SpringTxConfiguration.class); IAccountService accountService = (IAccountService)context.getBean("accountService"); accountService.transfer("aaa","bbb",100f); } }

浙公网安备 33010602011771号