Spring 4 - AOP

Spring 4 - AOP,第1张

Spring 4 - AOP

Spring - AOP
  • 1.环境准备(省略导包)
    • 0.Pom
    • 1.创建数据库/表
    • 2.entity
    • 3.mapper
    • 4.execption
    • 5.service
    • 6.xml (cn.kgc.mapper)
    • 7.applicationContext.xml
    • 8.mybatis-config.xml
    • 9.TestBuy
  • 2.企业级常用版A-注解实现事务
    • 2.1 applicationContext.xml
    • 2.2 BuyComputerServiceImpl (第一种)
    • 2.3 BuyComputerServiceImpl (第二种)
  • 3.特殊项目复杂版B-去除事务注解版
    • 3.0 引用:
    • 3.1 BuyComputerServiceImpl
    • 3.2 applicationContext.xml

1.环境准备(省略导包) 0.Pom

    
      org.springframework
      spring-aspects
      5.2.5.RELEASE
    

==》第一个依赖是针对下面的A B事务

  
    
      org.springframework
      spring-context
      5.2.5.RELEASE
    
    
    
      org.springframework
      spring-tx
      5.2.5.RELEASE
    
    
      org.springframework
      spring-jdbc
      5.2.5.RELEASE
    
    
    
      org.mybatis
      mybatis
      3.5.1
    
    
    
      org.mybatis
      mybatis-spring
      1.3.1
    
    
    
      mysql
      mysql-connector-java
      5.1.36

这边虚拟机的数据库是5版本的。

    
    
    
      com.alibaba
      druid
      1.1.12
    
    
    
      junit
      junit
      4.11
      test


      org.projectlombok
      lombok
      1.18.20
      provided
    
  
1.创建数据库/表

基于Linux系统的虚拟机

CREATE TABLE `t_computer` (
  `id` int(32) NOT NULL AUTO_INCREMENT,
  `cname` varchar(32) DEFAULT NULL,
  `cmount` int(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `t_store` (
  `id` int(32) NOT NULL AUTO_INCREMENT,
  `cid` int(32) DEFAULT NULL,
  `c_num` int(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into t_computer(id,cname,cmount) values(111,'华为',100);
2.entity

(1)Computer

@Getter
@Setter
public class Computer {
    private Integer id;
    private String name;
    private Integer cmount;
}

(2)Store

@Getter
@Setter
public class Store {
    private Integer id;
    private Integer cid;
    private Integer cNum;
}
3.mapper

(1) ComputerMapper

public interface ComputerMapper {
    //更新Computer表
    Integer updateComputer(Computer computer);
    //查询Computer表
    Computer findComputer(Integer id);
}

(2) StoreMapper

public interface StoreMapper {
    Integer insertStore(Store store);
}
4.execption
public class NotEnoughException extends RuntimeException {
    public NotEnoughException() { }

    public NotEnoughException(String message) {
        super(message);
    }
}
5.service

(1)BuyComputerService

public interface BuyComputerService {
    //购买电脑
    void buy(Integer computerId,Integer nums);
}

(2)BuyComputerServiceImpl

@Service("BuyComputerService")
public class BuyComputerServiceImpl implements BuyComputerService {
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private ComputerMapper computerMapper;
    @Override
    public void buy(Integer computerId, Integer nums) {
        //1.更新库存表store
        Store store = new Store();
        store.setCid(computerId);// 购买什么电脑
        store.setCNum(nums);// 购买几台电脑
        storeMapper.insertStore(store);
        //2.校验参数
        //通过电脑编号查询电脑对象
        Computer computer = computerMapper.findComputer(computerId);
        if (computer == null){
            //判断如果没有该电脑,报异常,抛电脑不存在异常
            throw new NullPointerException("编号是:" + computerId + ",电脑不存在");
        }else if(computer.getCmount() < nums ){
            //判断如果购买的电脑的数量大于实际的库存数,则抛出异常,抛电脑库存不足
            throw new NotEnoughException("编号是:" + computerId + ",电脑库存不足");
        }
        //2.更新电脑表数据computer
        Computer c = new Computer();
        c.setId(computerId);
        c.setCmount(nums);
        computerMapper.updateComputer(c);
    }
}

注意点:
@Autowired
有这个注释就省去了构造方法或者get,set方法来设置xxx属性

6.xml (cn.kgc.mapper)

(1)ComputerMapper.xml




    
    
        update t_computer set cmount = cmount - #{cmount} where id = #{id}
    

    

(2)StoreMapper.xml





    
        insert into t_store(cid,c_num) values (#{cid},#{cNum})
    

7.applicationContext.xml
    
        
        
        
    
    
    
        
        
    
    
    
        
    
    

8.mybatis-config.xml



    
        
        
    
    
        
        
    

9.TestBuy
public class TestBuy {
	    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        BuyComputerService buyComputerService = (BuyComputerService) ac.getBean("BuyComputerService");
    @Test
    public void test01(){
        //正常传参情况下的测试
        buyComputerService.buy(111,10);
    }
    @Test
    public void test02(){
        //测试购物错误编码的电脑
        buyComputerService.buy(112,10);
    }
    @Test
    public void test03(){
        //测试购买数超过库存数
        buyComputerService.buy(111,1000);
    }
}

结论:
第一个是能有结果。

而第二个第三个虽然报错,
但是t_score表里面的值会增加,是个bug。

说明:
需要做到报错就不会有变化,这时候就需要用到事务了。

2.企业级常用版A-注解实现事务 2.1 applicationContext.xml

第一步 声明事务管理器对象

set 注入 引入事务的机制
配置事务管理器,事务依赖于数据源所产生的连接对象,
只有连接对象创建成功了才能够处理事务


    
 

概念:
DataSourceTransactionManager 数据源事务管理器,
用于对单个数据源进行事务管理,通常用于JDBC事务管理或者mybatis事务管理。

第二步 开启事务注解驱动,告诉spring使用注解管理事务

去识别注解 并通过注解开启事务

注意点: 引入标签的时候注意要带有 tx

spring使用AOP机制,创建@Transactional所在的类代理,给方法加入事务的功能

(底层:在你的业务方法执行之前,先开启事务,在业务方法之后提交或回滚事务)


xml导包附注:



2.2 BuyComputerServiceImpl (第一种)
 @Transactional(
            propagation = Propagation.REQUIRED, 
//配置该属性的含义代表调用该方法默认开启事务(传播性)
//即使不写REQUIRED这句话,也是默认这个。

            isolation = Isolation.DEFAULT,  
//配置该属性的含义代表(支持事务的隔离性)使用默认的隔离级别(多事务之间相互隔离,互不影响)

            readonly = false,               
//配置该属性的含义代表支持增删改的 *** 作  默认是false
//readOnly配置为true的含义为只读 只能查,不能增删改,所以默认false
//查询没有事务,不需要事务,也不支持事务

            rollbackFor = {
                    NullPointerException.class,
                    NotEnoughException.class
            }
//配置该属性的含义代表如果方法中出现对应的两个异常,则该方法执行回滚 *** 作
    )

说明:
1.spring事务传播机制(共有7种):

  1. REQUIRED
    支持当前事务,如果没有事务会创建一个新的事务
  2. SUPPORTS
    支持当前事务,如果没有事务的话以非事务方式执行
  3. NEVER
    以非事务方式进行,如果存在事务则抛出异常

2.rollbackFor:
表示发生制定的异常一定回滚

上面都是默认的,所以光写一个注解也行,就是第二种方法。

2.3 BuyComputerServiceImpl (第二种)

2.2 中的事务注解在企业中会替换成
@Transactional(企业中一般都使用默认配置)

注意点:

  1. 在哪需要事务就写在哪的方法,写在类上就是所有的都加事务,可能不太好。

  2. 只有增删改需要事务,而查询不需要。

  3. 事务只放在service层。

写法:
案例中添加在BuyComputerServiceImpl的buy方法上

@Override
@Transactional
public void buy(Integer computerId, Integer nums) { }

结果:
这时候就对了。利用的是事务机制。

引入:
一千个包都需要用事务,写的时候会很烦,所以用下面的B。

下面利用的是AOP机制 》AOP去实现事务

3.特殊项目复杂版B-去除事务注解版

假如很多包都需要事务,那么我们就可以提取出来,
做一个单独的模块,让这个模块横穿所有的小模块,
在这个模块上写事务,让横穿的那些小模块都有这个特性
用的就是AOP特性,AOP去实现事务。

3.0 引用:

原文链接: https://blog.csdn.net/z3881006/article/details/79020166

在使用spring框架配置AOP的时候,
不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点"。

例如 定义切入点表达式 execution(* com.sample.service.impl..*.*(..))

》对哪个包 哪个类需要事务就去切,然后放在切面中,就实现了事务

execution()是最常用的切点函数,其语法如下所示:

整个表达式可以分为五个部分:

  1. execution(): 表达式主体。

  2. 第一个*号:表示返回类型,*号表示所有的类型。

  3. 包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。

  4. 第二个*号:表示类名,*号表示所有的类。

  5. *(…):最后这个星号表示方法名,*号表示所有的方法,
    后面括弧里面表示方法的参数,两个句点表示任何参数。

3.1 BuyComputerServiceImpl

去除 @Transactional

3.2 applicationContext.xml

基于1 环境准备中的 applicationContext.xml


    




    
    
        
        
        
  		 
    


    
    
    
    


----2021.12.10&12.11

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5660828.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存