Spring第三阶段

Spring

Spring的AOP的注解

AOP注解的入门

  1. 创建项目,引入jar包
  2. 创建接口跟实现类
  3. 将类的创建交给Spring
<!-- 配置目标类-->
        <bean id="customerDao" class="com.itheima.aop.demo1.CustomerDaoImpl">
        </bean>
  1. 编写切面类
  2. 开启AOP的注解 <aop:aspectj-autoproxy />
  3. 切面类的注解开发 @Aspect
  4. 在方法上加注解

    • 前置增强 @Before(value="execution(* com.spring...)")
    • 后置增强,可以添加返回值 @AfterReturning(value="execution(* com.spring...)",returning="obj")
    • 环绕增 @Around(value="execution(* com.spring...)")
    • 异常捕获,可以获得异常信息 @AfterThrowing(value="execution(* com.spring...)",throwing="ex")
    • 最终增强 @After(value="execution(* com.spring...)")

    • 可以把切入点注解提取出来,在最后加一个没有内容的方法,然后上面注解加这个,然后,上面的每一个方法上需要切入哪,只需要在value中加一个 类名.方法名 即可。

@Pointcut(value="execution(* com.spring...)")
private void pointCut01(){}

Spring的JDBC

Spring 的JDBC的模板

Spring是EE开发的一站式框架,一站式框架就有每层的解决方案(包括持久层)。

Spring的JDBC模板的入门

spring里面了很多对于持久层的解决方案。(JDBC,hibernate均有)

  1. 创建项目,引入Spring的需要的jar包,还有Spring核心包中的两个包jdbc,tx 还有连接数据库的包 connection,Spring的版本还需要引入AOP的包
  2. 使用JDBC的模板
//创建连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//设置连接数据库的相关的参数
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///数据库");
dataSource.setUsername(" ");
dataSource.setPassword(" ");

JdbcTemplate jdbctemplate = new JdbcTemplate();
JdbcTemplate.setDataSource(dataSource);
jdbctemplate.update("sql语句",null,"name","password");
  • 这种方法是不好的,因为每次使用的时候还需要创建连接池,所以把连接池交给Spring管理

把连接池交给Spring管理

  • 创建xml配置文件,引入beans的约束
  • 配置内置连接池
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="" />
  <property name="url" value="" />
  <property name="username" value="" />
  <property name="password" value="" />
</bean>
  • 把JDBC的模板交给Spring管理
<bean id="jdbcTemplate" class="jdbcTemplate的路劲" >
    <property name="dataSource" ref="dataSource" />
</bean>
//这里的name必须为dataSource,因为用的是JDBC的模板
  • 测试类:

用JUnit跟Springde整合

@RunWith(SpringJUnit4ClassRunner.class)
@contextConfiguration("classpath:applicationContext.xml")
public class JdbcTemplateDemo2{
    @Resource(name="jdbcTemplate")
    private JdbcTemplate jdbcTemplate;

    @Test
    public void demo01(){
         jdbcTemplate.update("insert into account values (?,?)""张三"100d),;
    }
}

引入外界连接池

dpcp连接池
  • 导包:依赖包中apache的commons中的dpcp跟pool,用之前的也行,跟这个一样
  • 配置DBCP连接池
//配置DBCP的连接池
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="com.mysql,jdbc.Driver" />
  <property name="url" value="jdbc:mysql:///数据库" />
  <property name="username" value="" />
  <property name="password" value="" />
</bean>
  • 测试跟默认的一样
c3p0的连接池
  • 导包,依赖包中c3p0的包
  • 配置连接池,注意:配置属性跟之前的不一样
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  <property name="driverClass" value="com.mysql,jdbc.Driver" />
  <property name="jdbcUrl" value="jdbc:mysql:///数据库" />
  <property name="user" value="" />
  <property name="password" value="" />
</bean>

提取属性文件(连接数据库的信息)

即使用配置文件,如果需要把项目交给别人也要改配置文件,所以提取出一个属性文件,改的时候只改属性文件即可

  • 定义属性文件jdbc.properties
    01

  • 在Spring中配置文件引入属性文件:

    1. 通过<bean>引入
<bean  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:jdbc.prorerties">
</bean>

在配置配置文件:
02

  1. 但不经常用这个,经常用context标签引入
<context:property-placeholder location="classpath:jdbc.prorerties">
<!--  配置C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
   <property name="driverClass" value="${jdbc.driverClass}" />
   <property name="jdbcUrl" value="${jdbc.url}" />
   <property name="user" value="${jdbc.user}" />
   <property name="password" value="${jdbc.password}" />
</bean>

JDBC模板进行CURD操作

增删改
  • 增删改的方法是通用的:
    • update(sql语句,参数);

03

查询
  • 单个数 : T queryForObject(String sql,Class/<T/> requiredType,Object… args)
  • 某个对象 :T queryForObject(String sql,RowMapper/<T/> rowMapper ,Object… args);
  • List集合 :List/<T/> query(String sql,RowMapper/<T/> rowMapper,Object… args);

  • 查询属性

//查询id为1的账号的名称
String name=jdbcTemplate.queryForObject(sql语句,String.class,Object 参数);
  • 统计个数
Long count=jdbcTemplate.queryForObject(sql语句,Long.class,Object 参数);
  • 查询某个对象
    • RowMapper类似于DBUtils中的 ResultSetHandler
Account account=jdbcTemplate.queryForObject(sql语句,new MyRowMapper(),参数);

//可以创建一个内部类来实现RowMapper<T>
class MyRowMapper implements RowMapper<User>{
   @override
   public Account mapRow(ResultSet rs,int rowNum){
       Account account = new Account();
       account.setId(rs.getInt("id"));
       account.setName(rs.getString("name"));
       account.setMoney(rs.getDouble("money"));
       return account;
   }
}
  • 查询多个对象
List<Account> account = query(String sql,new MyRowMapper(),Object... args);
//当然也需要创建一个RowMapper<T>接口的实现类,跟上边用一个就行

Spring的事务

Spring的事务管理

事务的回顾
  • 事务的概念:
    • 逻辑上一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败
  • 事务的特性:
    • 原子性
    • 一致性
    • 隔离性
    • 持久性
  • 如果不考虑隔离性引发安全问题
    • 读问题
      • 脏读
      • 不可重复读
      • 虚读
    • 写问题
      • 丢失更新
  • 解决读问题
    • 设置事务隔离级别
      • read uncommitted
      • read committed
      • repeatable read
      • serializable
Spring的事务管理的API
  • PlatformTransactionManager:平台事务管理器(Spring中真正管理事务的对象)
    • DataSourceTransactionManager :使用JDBC操作进行事务管理时候使用
    • HibernateTransactionManager :使用Hibernate框架进行事务管理时候使用
  • TransactionDefinition :事务的定义信息
    • 事务的隔离级别
    • 事务的传播行为
    • 事务是否只读
    • 事务超时信息
  • TransactionStatus :事务的状态对象
    • 是否已经完成
    • 是否有保存点
  • 三个对象的关系:
    • Spring通过TransactionDefinition对事务进行定义,使用PlatformTransactionManager根据定义信息进行事务的管理,在事务管理过程中产生一些状态,将状态存入到TransactionStatus中。
事务的传播行为的作用和含义
  • 事务传播行为的作用

    • 事务的传播行为:解决复杂的事务的操作,业务层之间代码的相互调用 propagation
      04
  • 事务传播行为的取值:记标红的那个即可,主要是第一个
    05
    根据上两幅图做出的解释:
    06

Spring的事务管理的方式
  • 编程式事务管理: 手动编写代码实现事务管理
  • 声明式事务管理: 通过配置实现事务管理
    • xml的配置方式
    • 注解方式

Spring的事务管理实现:

搭建事务管理的基本环境

用转账的案例,先写出JDBC模板:

  • 编写Dao
public class AccountDaoImpl implements AccountDao {

    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void outMoney(String from, Double money) {
        jdbcTemplate.update("update account set money = money - ? where name = ?", money,from);
    }

    @Override
    public void inMoney(String to, Double money) {
        jdbcTemplate.update("update account set money = money + ? where name = ?", money,to);
    }

}
  • 配置Dao
<!-- 引入外部属性文件:方式二:通过context标签引入 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 配置C3P0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- 将JDBC的模板交给Spring管理 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置DAO -->
    <bean id="accountDao" class="com.itheima.tx.demo1.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
  • 编写Service
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    /**
     * from:转出账号
     * to:转入账号
     * money:转账金额
     */
    public void transfer(String from, String to, Double money) {
        accountDao.outMoney(from, money);
        accountDao.inMoney(to, money);
    }

}
  • 配置Service
<!-- 配置Service -->
    <bean id="accountService" class="com.itheima.tx.demo1.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>
  • 编写测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class TransactionDemo1 {
    @Resource(name="accountService")
    private AccountService accountService;

    @Test
    public void demo1(){
        accountService.transfer("郝强勇", "郝如花", 1000d);
    }
}
编程式事务管理
  • 配置事务管理器: :事务管理器的名称必须是transactionManager
<!-- 配置事务管理器:Spring真正管理事务的类 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
  • 配置事务管理模板
//配置事务管理的模板
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">   <property name="transactionManager" ref="transactionManager" />
</bean>
  • 在业务层注入事务管理的模板
<!-- 配置Service -->
    <bean id="accountService" class="com.itheima.tx.demo1.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <!-- 事务管理模板的注入 -->
        <property name="transactionTemplate" ref="transactionTemplate"/>
    </bean>
  • 改写业务层
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    // 提供事务管理模板注入:
    private TransactionTemplate transactionTemplate;
    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    /**
     * from:转出账号
     * to:转入账号
     * money:转账金额
     */
    public void transfer(final String from, final String to, final Double money) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                accountDao.outMoney(from, money);
                int d = 1/ 0;
                accountDao.inMoney(to, money);
            }
        });

    }

}
声明式事务管理(底层用的就是AOP)
XML方式
  • 引入Aop的jar包
  • 恢复一下转账的环境
  • 配置事务管理器
<!-- 配置事务管理器 -->
    <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="save*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="find*" read-only="true"/> -->
            <tx:method name="transfer" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

//propagaion :传播行为
isolation :隔离级别
read-only :是否为只读
rollback-for :发生哪些异常事务会回滚,默认情况下,任何异常都会回滚
no-rollback-for :发生哪些异常事务不会回滚
  • AOP的配置
 <!-- AOP的配置-->
    <aop:config>
      <aop:pointcut expression="execution(* com.itheima.tx.demo2.AccountServiceImpl.transfer(..))"  id="pointcut1"/>
     <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
    </aop:config>
注解方式
  • 恢复开发环境
  • 配置事务管理器
  • 开启注解事务
<tx:annotation-driven transaction-manager="transactionManager" />
  • 在要加注解的类上加一个@Transactional
    • 要想加属性后边加一个(),按提示写
      08
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值