Spring的配置,IOC和AOP详解与总结

1.需要导入的jar包

  • 必须的jar包

      commons-logging-1.1.3.jar
      spring-beans-4.0.0.RELEASE.jar
      spring-context-4.0.0.RELEASE.jar
      spring-core-4.0.0.RELEASE.jar
      spring-expression-4.0.0.RELEASE.jar
    
  • 通过注解方式配置bean需要的jar包

    spring-aop-4.0.0.RELEASE.jar
    
  • 连接Mysql数据库需要导入的jar包

          c3p0-0.9.1.2.jar
          mysql-connector-java-5.1.37-bin.jar
    
  • AOP、配置事务需要的jar包

      com.springsource.net.sf.cglib-2.2.0.jar
      com.springsource.org.aopalliance-1.0.0.jar
      com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
      spring-aspects-4.0.0.RELEASE.jar
    
  • 配置JdbcTemplate需要的jar包

    spring-jdbc-4.0.0.RELEASE.jar
    spring-orm-4.0.0.RELEASE.jar
    spring-tx-4.0.0.RELEASE.jar
    

2.创建IOC容器

ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
  • beans.xml的Spring的配置文件需要放到源码包(如src)下

3.bean的配置

  • set注入(属性注入)

  • 通过这中方式配置bean,IOC容器首先通过类的无参构造器创建对象,然后通过set方法将属性注入到对象中

    //通过property标签配置bean,我们也称为set注入 
      <bean id="book" class="com.atguigu.spring.bean.Book">
           <property name="id" value="1"></property>
           <property name="title" value="金瓶梅"></property>
           <property name="author" value="兰陵笑笑生"></property>
           <property name="price" value="2.5"></property>
           <property name="sales" value="100000"></property>
      </bean>
    
    • 通过id属性给每一个bean起一个名字,id属性值不能重复,在IOC容器中必须要保证是唯一的,class属性用来设置Book类的全类名
    • name属性值是Book类中的属性,不能任意指定
  • 构造器注入

  • 通过这种方式配置bean,IOC容器根据类的构造器创建对象

    // 通过constructor-arg标签配置bean,我们称构造器注入
      <bean id="book2" class="com.atguigu.spring.bean.Book">
           <constructor-arg value="2"></constructor-arg>
           <constructor-arg value="三国演义"></constructor-arg>
           <constructor-arg value="罗贯中"></constructor-arg>
           <constructor-arg value="28.00"></constructor-arg>
           <constructor-arg value="100"></constructor-arg>
      </bean>
    
  • 通过这种方式配置必备要保证Book类中有对应的包含5个参数的构造器

  • 引入外部bean

  • 引用其他的bean

     <bean id="cartItem" class="com.atguigu.spring.bean.CartItem">
         ref属性:用来引用在IOC容器中配置的其他的bean,其属性值是其他bean的id属性值 
        <property name="book" ref="book">
        </property>
       <property name="count" value="10"></property>
       </ bean>
    
  • 通过ref属性来引入其他的bean,ref的属性值是在IOC容器中配置的其他bean的id属性值

  • 引入外部属性文件(通常用来配置数据源)

  • 包含了连接数据库有关信息的配置文件db.properties

     jdbc.user=root
     jdbc.password=root
     jdbc.driverClass=com.mysql.jdbc.Driver
     jdbc.jdbcUrl=jdbc:mysql:///test
     
     jdbc.initPoolSize=5
     jdbc.maxPoolSize=10
     jdbc.minPoolSize=2  
    

在spring的配置文件中引入上面的文件

//引入外部属性文件 
 <context:property-placeholder location="classpath:db.properties"/>
 <!-- 获取数据库连接 -->
 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      <property name="user" value="${jdbc.user}"></property>
      <property name="password" value="${jdbc.password}"></property>
      <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
      <property name="driverClass" value="${jdbc.driverClass}"></property>
      <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
      <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
      <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
 </bean>
  • 获取bean的方式
    1.通过id属性值获取
    2.通过类型获取
    (1) 通过这种方式获取bean如果IOC中有多个会抛异常
  • bean的作用域
    • 默认情况下,IOC容器一创建就会创建IOC容器中配置的bean的实例,而且是单例的,任何时候获取得到的都是同一个对象

    • 我们可以通过bean的scope属性来设置bean时多例的,这是每次获取bean时获取的是一个新的对象,而且IOC容器一创建不会创建IOC容器中配置的bean的实例,只有每次调用getBean()时才会创建对象

       bean的作用域 
           <!-- singleton:默认,IOC容器一创建就创建该对象,而且是一个单例的 -->
       <!-- prototype:IOC容器创建时不会创建该对象,每次获取bean时才会创建对象,而且每次获取都会创建一个新的对象,是多例的 -->
       <bean id="student" class="com.atguigu.spring.bean.Student" scope="prototype">
        <property name="id" value="1"></property>
        <property name="name" value="苍老师"></property>
       </bean>
      

4.通过注解的方式配置bean

@Component
用来标识一个普通组件
@Repository
用来标识一个持久化层的组件
@Service
用来标识一个业务逻辑层的组件
@Controller
用来标识一个表示层的控制器组件

  • 在Spring的配置文件中配置自动扫描的包

      <!-- base-package属性:用来设置要扫描的包及其子包,如果要扫描多个包中间使用逗号分隔 -->
      <!-- resource-pattern属性:用来精确设置要扫描的子包 -->
      <context:component-scan base-package="com.atguigu.spring.annotation"></context:component-scan>
    

    通过在类上添加以上注解及配置自动扫描的包之后,被标识的类就会自动被IOC容器管理,在IOC容器中的bean的id属性值默认是类的首字母小写

我们也可以通过value属性值指定bean的id属性值
例如:@Repository(value=“bookDao”)或@Repository(“bookDao”)
@Autowired
通过该注解将某个类的属性进行自动注入
自动注入的规则:
1)首先检查要注入的属性的类型
2)根据属性的类型进行自动注入
3)如果该属性的类型在IOC容器中匹配到多个,以属性名作为bean的id属性值进行匹配
4)通过@Qualifier注解来指定要匹配的bean的id属性值

如:@Qualifier(value=“bookDao”)或@Qualifier(“bookDao”)

将IOC容器中id属性值是bookDao的bean装配进来
如果属性最终不能自动装配,默认会抛异常,我们可以通过requireds属性来设置某个属性不是必须的

如:@Autowired(required=false)
通过@Scope(value=“prototype”)来设置某个bean时多例的
在Spring的配置文件中配置要扫描那些组件

 <!-- 自定义要扫描的组件的前提是use-default-filters的属性值改为false -->
 <context:component-scan base-package="com.atguigu.spring.annotation" use-default-filters="false">
      
 type属性值是annotation时,expression的属性值是注解的全类名
 type属性值是assignable时,expression的属性值是类或接口的全类名 
      
      <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
          <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
          <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
 </context:component-scan>
  • 在Spring的配置文件中配置不扫描那些组件
 <context:component-scan base-package="com.atguigu.spring.annotation">
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
      <context:exclude-filter type="assignable" expression="com.atguigu.spring.annotation.service.impl.UserServiceImpl"/>
      <context:exclude-filter type="assignable" expression="com.atguigu.spring.annotation.handler.UserHandler"/>
 </context:component-scan>

5.AOP
@Aspect
添加到类上
用来声明一个类是一个切面类,同时还需要通过@Component注解将该切面类添加到IOC容器中

@Pointcut
添加到方法上
用来声明一个切入点表达式

@Before
添加到方法上
用来声明前置通知,在方法执行之前调用

@After
添加到方法上
用来声明后置通知,在方法调用完成之后执行(不管是否发生异常)

@AfterReturnning
添加到方法上
用来声明一个返回通知,在方法执行结束得到返回值时调用

@AfterThrowing

添加到方法上
用来声明一个异常通知,当方法方式异常时调用
@Around
添加到方法上
用来声明一个环绕通知,相当于动态代理的全过程

@Order(value=1)
添加到类上
用来声明切面的优先级
value值的范围的Integer类型的范围,值越小优先级越高

具体实现代码

创建一个切面类: 该类除了使用@Aspect声明为一个切面类之外还需要通过@Component将它加入到IOC容器中
 *
 * @author HanYanBing
 *  */
@Order(-1)//通过@Order注解设置切面的优先级,值越小优先级越高,值是Integer的范围
@Aspect
@Component
public class LoggingAspect {
     
     //声明一个切入点表达式
     @Pointcut(value = "execution(* com.atguigu.spring.aop.ArithmeticCalculateImpl.*(..))")
     public void pointCut(){}

     /*
      *   1.@Before(value="execution(public int com.atguigu.spring.aop.ArithmeticCalculateImpl.add(int, int))")
      *        --只有调用ArithmeticCalculateImpl中的add方法时才会调用前置通知的方法
      *  2.@Before(value="execution(public int com.atguigu.spring.aop.ArithmeticCalculateImpl.*(int, int))")
      *        --调用ArithmeticCalculateImpl中的所有方法时调用前置通知的方法
      *  3.@Before(value="execution(public int com.atguigu.spring.aop.ArithmeticCalculateImpl.*(..))")
      *   --调用ArithmeticCalculateImpl中的所有方法时(不考虑参数的个数及类型)调用前置通知的方法
      *  ★4.@Before(value="execution(* com.atguigu.spring.aop.ArithmeticCalculateImpl.*(..))")
      *   --调用ArithmeticCalculateImpl中的所有方法时(不考虑权限修饰符和返回值类型及参数的个数及类型)调用前置通知的方法
      *   5.@Before(value="execution(* *.*(..))")
      *        --调用所有类中的所有方法时都会调用前置通知的方法
      */
     // 前置通知:在方法调用前执行
     @Before(value = "execution(* com.atguigu.spring.aop.ArithmeticCalculateImpl.*(..))")
     public void beforeMethod(JoinPoint joinPoint) {
          // 获取方法名
          String name = joinPoint.getSignature().getName();
          // 获取传入方法中的参数
          Object[] args = joinPoint.getArgs();
          System.out.println("[★★★Logging]:The method " + name + " begins with " + Arrays.asList(args));
     }

     // 后置通知:在方法调用后执行(不管是否发生异常)
     @After("execution(* com.atguigu.spring.aop.ArithmeticCalculateImpl.*(..))")
     public void afterMethod(JoinPoint joinPoint) {
          // 获取方法名
          String name = joinPoint.getSignature().getName();
          System.out.println("[★★★Logging]:The method " + name + " ends");
     }

     // 返回通知:在方法执行完之后调用
     @AfterReturning(value = "execution(* com.atguigu.spring.aop.ArithmeticCalculateImpl.*(..))", returning = "result")
     public void afterReturn(JoinPoint joinPoint, Object result) {
          // 获取方法名
          String name = joinPoint.getSignature().getName();
          System.out.println("[★★★Logging]:The method " + name + " returns " + result);
     }

     // 异常通知:在方法执行出现异常时调用
     @AfterThrowing(value = "execution(* com.atguigu.spring.aop.ArithmeticCalculateImpl.*(..))", throwing = "e")
     public void throwMethod(JoinPoint joinPoint, Throwable e) {
          // 获取方法名
          String name = joinPoint.getSignature().getName();
          System.out.println("[★★★Logging]:The method "+name+" occurs exception "+e);
     }
     
     //环绕通知:相当于动态代理的全过程
     @Around("pointCut()")
     public Object around(ProceedingJoinPoint pjp){
          //获取方法名
          String name = pjp.getSignature().getName();
          //获取方法中传入的参数
          Object[] args = pjp.getArgs();
          //前置通知
          System.out.println("[★★★★★Logging]:The method " + name + " begins with " + Arrays.asList(args));
          Object result = null;
          try {
              //调用方法
              result = pjp.proceed();
              //返回通知
              System.out.println("[★★★★★Logging]:The method " + name + " returns " + result);
          } catch (Throwable e) {
              //异常通知
              System.out.println("[★★★★★Logging]:The method "+name+" occurs exception "+e);
//            e.printStackTrace();
          } finally {
              //后置通知
              System.out.println("[★★★★★Logging]:The method " + name + " ends");
          }
          return result;
     }
}
  • 通过xml配置文件的方式配置AOP
<?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"
     xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

     <!-- 配置数学计算的实现类的bean -->
     <bean id="arithmeticCalculate" class="com.atguigu.spring.aop.xml.ArithmeticCalculateImpl"></bean>
     <!-- 配置切面bean -->
     <bean id="loggingAspect" class="com.atguigu.spring.aop.xml.LoggingAspect"></bean>
     
     <!-- 配置AOP -->
     <aop:config>
          <!-- 配置切入点表达式 -->
          <aop:pointcut expression="execution(* com.atguigu.spring.aop.xml.ArithmeticCalculateImpl.*(..))"
                             id="poinCut"/>
          <!-- 配置切面-->
          <aop:aspect ref="loggingAspect">
              <!-- 配置前置通知 -->
              <aop:before method="beforeMethod" pointcut-ref="poinCut"/>
              <!-- 返回通知 -->
              <aop:after-returning method="afterReturn" pointcut-ref="poinCut" returning="result"/>
              <!-- 异常通知 -->
              <aop:after-throwing method="throwMethod" pointcut-ref="poinCut" throwing="e"/>
              <!-- 后置通知 -->
              <aop:after method="afterMethod" pointcut-ref="poinCut"/>
          </aop:aspect>
     </aop:config>
</beans>

6.配置JdbcTemplate
在Spring中配置JdbcTemplate

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsd">

     <context:component-scan base-package="com.atguigu.spring.jdbc"></context:component-scan>

     <!-- 导入连接数据的有关信息的外部文件 -->
     <context:property-placeholder location="classpath:db.properties"/>
     <!-- 配置数据源 -->
     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          <property name="user" value="${jdbc.user}"></property>
          <property name="password" value="${jdbc.password}"></property>
          <property name="driverClass" value="${jdbc.driverClass}"></property>
          <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
          <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
          <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
          <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
     </bean>
     <!-- 配置JdbcTemplate -->
     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
          <property name="dataSource" ref="dataSource"></property>
     </bean>
     <!-- 配置NamedParameterJdbcTemplate -->
     <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
          <constructor-arg ref="dataSource"></constructor-arg>
     </bean>
</beans>
  • JdbcTemplate中封装了增删改、批量更新、获取一个对象、获取一个集合、获取一个单一值的方法
public class JdbcTemplateTest {

     //创建IOC容器对象
     ApplicationContext ioc = new ClassPathXmlApplicationContext("beans-jdbc.xml");
     //获取JdbcTemplate对象
     JdbcTemplate jdbcTemplate = (JdbcTemplate) ioc.getBean("jdbcTemplate");
     //获取NamedParameterJdbcTemplate对象
     NamedParameterJdbcTemplate npjt = (NamedParameterJdbcTemplate) ioc.getBean("namedParameterJdbcTemplate");
     
     @Test
     public void testDataSource() throws SQLException {
          DataSource dataSource = ioc.getBean(DataSource.class);
          System.out.println(dataSource.getConnection());
     }

     //通用的增删改
     @Test
     public void testUpdate(){
          String sql = "insert into employees(last_name,email,salary,dept_id) values(?,?,?,?)";
          jdbcTemplate.update(sql, "马蓉","mr@sz.com",25000,6);
     }
     //批量更新
     @Test
     public void testBatchUpdate(){
          String sql = "insert into employees(last_name,email,salary,dept_id) values(?,?,?,?)";
          //创建一个集合
          List<Object[]> batchArgs = new ArrayList<>();
          batchArgs.add(new Object[]{"王宝强","sg@ts.com",100,5});
          batchArgs.add(new Object[]{"宋喆","sz@sjj.com",1000,6});
          batchArgs.add(new Object[]{"白百何","bbh@yf.com",1000,6});
          batchArgs.add(new Object[]{"文章","wz@myl.com",10000,6});
          jdbcTemplate.batchUpdate(sql, batchArgs);
     }
     //获取一个对象的方法
     /**
      * 1.调用的不是queryForObject(String sql, Class<T> requiredType, Object... args)这个方法,而是
      *        queryForObject(String sql, RowMapper<T> rowMapper, Object... args)
      *            -RowMapper使用的实现类是BeanPropertyRowMapper(Class<T>),它就相当于Dbutils中的BeanHandler
      * 2.不支持级联属性的查询
      */
     @Test
     public void testGetBean(){
          String sql = "select id,last_name lastName,email,salary,dept_id from employees where id = ?";
          RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
          Employee employee = jdbcTemplate.queryForObject(sql, rowMapper, 4);
          System.out.println(employee);
     }
     //获取一个集合
     @Test
     public void testGetBeanList(){
          String sql = "select id,last_name lastName,email,salary from employees where id > ?";
          RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
          List<Employee> list = jdbcTemplate.query(sql, rowMapper,3);
          System.out.println(list);
     }
     //获取一个单一的值
     @Test
     public void testGetSingelValue(){
          String sql = "select count(*) from employees";
          Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);
          System.out.println(integer);
     }
     //使用具名参数的形式向数据库中插入一条数据
     //可以通过具名参数给占位符起一个名字,这时我们填充占位符时只需要根据具名参数的名字填充占位符即可,不需要在意它们的顺序
     @Test
     public void testNamedPrameterJdbcTemplate(){
          String sql = "insert into employees(last_name,email,salary,dept_id) values(:ln,:em,:sy,:dpt)";
          //创建一个Map
          Map<String , Object> parmMap = new HashMap<>();
          parmMap.put("ln", "甘露露");
          parmMap.put("sy", 500);
          parmMap.put("em", "gll@sll.com");
          parmMap.put("dpt", 6);
          npjt.update(sql, parmMap);
     }
     //测试SqlParameterSource
     /*
      * 使用SqlParameterSource时:
      *        1.具名参数的值要与对象的属性值保持一致
      *        2.SqlParameterSource的实现类使用BeanPropertySqlParameterSource
      */
     @Test
     public void testSqlParameterSource(){
          String sql = "insert into departments(name) values(:name)";
          Department department = new Department();
          department.setName("财务部");
          SqlParameterSource sqlSource = new BeanPropertySqlParameterSource(department);
          npjt.update(sql, sqlSource);
     }
     @Test
     public void testDepartmentDao(){
          DepartmentDao departmentDao = (DepartmentDao) ioc.getBean("departmentDao");
          Department dept = new Department();
          dept.setName("公关部");
          departmentDao.insertDept(dept );
     }

7.给方法添加事务
配置事务管理器

<!-- 配置事务管理器 -->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource"></property>
     </bean>
<!-- 配置事务注解起作用 -->
     <!-- transaction-manager默认值是transactionManager,如果事务管理器的id属性值为transactionManager,transaction-manager属性可以省略 -->
     <tx:annotation-driven />

通过@Transactional注解添加事务
~~~~~~~~如果@Transactional添加到类上
~~~~~~~~~~~~~~类中所有的方法都添加了事务

  • 如果@Transactional只添加到了方法上
    • 只有这一个方法添加了事务
      事务中的一些属性
@Service("bookShopService")
public class BookShopServiceImpl implements BookShopService {

     @Autowired
     private BookShopDao bookShopDao;
     /**
      * 事务的传播行为:一个方法运行在一个添加了事务的方法中,当前方法是开启一个新事务还是使用原来的事务
      *   --通过propagation设置事务的传播行为:Propagation.REQUIRED,默认,使用原来的事务
      *                                       Propagation.REQUIRES_NEW,开启一个新事务
      * 事务的隔离级别:通过isolation设置事务的隔离级别
      *   -Mysql默认的隔离级别是Isolation.REPEATABLE_READ;Oracle默认的隔离级别是Isolation.READ_COMMITTED
      *   -常用的隔离级别:Isolation.READ_COMMITTED 读已提交
      * 通过rollbackFor、rollbackForClassName和noRollbackFor、noRollbackForClassName设置出现那些异常回滚和不回滚
      * 通过readOnly=true设置该操作是一个只读的,一般查询的方法中会设置该属性
      * timeout属性:用来设置事务的超时时间,单位是秒
      */
     @Transactional(propagation=Propagation.REQUIRES_NEW,isolation=Isolation.READ_COMMITTED,
                        noRollbackForClassName={"ArithmeticException"},timeout=1,readOnly=true)
     @Override
     public void purchase(int userId, String isbn) {
          
          //1.获取图书的价格
          double bookPrice = bookShopDao.getBookPrice(isbn);
//        System.out.println(bookPrice);
//        double bookPrice2 = bookShopDao.getBookPrice(isbn);
//        System.out.println(bookPrice2);
          //2.更新图书的库存
          bookShopDao.updateBookStock(isbn);
//        int a = 10/0;
//        //3.更新用户的余额
          bookShopDao.updateAccountBanlance(userId, bookPrice);
          try {
              Thread.sleep(5000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
     }
     
     
}

  • 通过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"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
     <!-- 设置自动扫描的包 -->
     <context:component-scan base-package="com.atguigu.spring.transaction.xml"></context:component-scan>

     <!-- 导入连接数据的有关信息的外部文件 -->
     <context:property-placeholder location="classpath:db2.properties"/>
     
     <!-- 配置数据源 -->
     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          <property name="user" value="${jdbc.user}"></property>
          <property name="password" value="${jdbc.password}"></property>
          <property name="driverClass" value="${jdbc.driverClass}"></property>
          <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
          <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
          <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
          <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
     </bean>
     
     <!-- 配置JdbcTemplate -->
     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
          <property name="dataSource" ref="dataSource"></property>
     </bean>
     
     <!-- 配置事务管理器 -->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource"></property>
     </bean>

     <!-- 配置事务 -->
     <tx:advice id="txAdvice">
          <!-- 配置要添加事务的方法 -->
          <tx:attributes>
              <tx:method name="purchase" propagation="REQUIRED"/>
              <tx:method name="get*" read-only="true"/>
              <tx:method name="*"/>
          </tx:attributes>
     </tx:advice>
     <!-- 配置AOP-->
     <aop:config>
          <!-- 配置切入点 -->
          <aop:pointcut expression="execution(* com.atguigu.spring.transaction.xml.BookShopServiceImpl.*(..))"
                   id="txPointCut"/>
          <!-- 配置切入点与事务之间的关联关系 -->      
          <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
     </aop:config>
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值