Spring-AOP与事务(学习记录)

什么是AOP?

AOP又称面向切面编程,简单来说就是在不影响主业务的情况下去增加其他的功能,举个例子:就是小明妈妈叫小明去超市买盐,这里的主要业务就是买盐,但小明在超市可以在买盐之前去买水果,然后去买盐,也可以买盐后,再去买其他的,只要不影响主业务,又想添加新功能,都可以使用AOP来解决。

AOP的相关术语

  • Target(目标对象):代理的目标对象

  • Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类

  • Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring,,这些点指的是方法,因为spring只支持方法类型的连接点

  • Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义

  • Advice(通知/增强):所谓通知是指拦截Joinpoint之后所要做的事情就是通知

  • Aspect(切面):是切入点和通知(引介)的结合

  • Weaving (织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入

入门案例(注解方式)

1.导入坐标:

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.8</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

2.创建service包,并在包下定义一个类

public interface ShoppingService {
    public String buyGoods(Integer payMoney);
}



//并写一个实现类
@Component("shoppingService")
public class ShoppingServiceImpl implements ShoppingService{
    @Override
    public String buyGoods(Integer payMoney) {
        System.out.println("小明支付的金额"+payMoney);

        Integer productMoney = 10;
        System.out.println("商品的金额:10元");
        int remainMoney = payMoney-productMoney;
        String result = "剩余金额"+remainMoney;
        System.out.println(result);

        return result;
    }
}

3.创建需要切入的方法

@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAnnotationAspectj {
    private final static String EXPRESSION = 
"execution(* org.example.service.*.*(..))";  
//指定要执行的方法的根路径

    //前置通知
    @Before(EXPRESSION)
    public void beforeAdvice(JoinPoint joinPoint){//joinPoint方法执行点
        System.out.println("========== 【Aspectj前置通知】 ==========");
    }

    //后置通知:方法正常执行后,有返回值,执行该后置通知:
//如果该方法执行出现异常,则不执行该后置通知
    @AfterReturning(value=EXPRESSION,returning = "returnVal")
    public void afterReturningAdvice(JoinPoint joinPoint,Object returnVal){
        System.out.println("========== 【Aspectj后置通知】 ==========");
    }

    //后置通知
    @After(EXPRESSION)
    public void afterAdvice(JoinPoint joinPoint){
        System.out.println("========== 【Aspectj后置通知】 ==========");
    }

    //环绕通知
    @Around(EXPRESSION)
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("##########【环绕通知中的前置通知】##########");
        Object returnVale = joinPoint.proceed();
        System.out.println("##########【环绕通知中的后置通知】##########");
        return returnVale;
    }

    // 异常通知:方法出现异常时,执行该通知
    @AfterThrowing(value = EXPRESSION,throwing = "ex")
    public void throwAdvice(JoinPoint joinPoint, Exception ex){
        System.out.println("********** 【Aspectj异常通知】执行开始 **********");
        System.out.println("出现异常:" + ex.getMessage());
        System.out.println("********** 【Aspectj异常通知】执行结束 **********");
    }

4.写配置类SpringConf这个类是用来代替applicationContext.xml的

@Configuration
@ComponentScan("org.example")
public class SpringConf {
}
//作用和applicationContext.xml一样,是将类交给容器管理,让容器来创建对象和管理对象

5.编写测试类

@Test
    public void test3(){
        ApplicationContext cxt = new AnnotationConfigApplicationContext(SpringConf.class);
        ShoppingService shoppingService = (ShoppingService) cxt.getBean("shoppingService");
        shoppingService.buyGoods(20);
    }

6.展示运行结果

手动添加一个异常时:

名称注解说明
前置通知@Before用于配置前置通知。指定增强的方法在切入点方法之前执行
后置通知@AfterReturning用于配置后置通知。指定增强的方法在切入点方法之后执行
环绕通知@Around用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行
异常抛出通知@AfterThrowing用于配置异常抛出通知。指定增强的方法在出现异常时执行
最终通知@After用于配置最终通知。无论增强方式执行是否有异常都会执行

什么是事务?

事务是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合。

事务的四大原则:

1.原子性(Atomicity):

一个事务已经是一个不可再分割的工作单位。事务中的全部操作要么都做;要么都不做

2.一致性(Consistency):

事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。

3.持久性(Durability):

一个事务一旦提交,它对数据库中数据的改变会永久存储起来。其他操作不会对它产生影响

4.隔离性(Isolation):

事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。

事务的隔离级别:

1.脏读 :在一个事务中读取到了另外一个事务修改的【未提交的数据】,而导致多次读取同一个数据返回的结果不一致 (必须要解决的)

2.不可重复读 : 在一个事务中读取到了另外一个事务修改的【已提交的数据】,而导致多次读取同一个数据返回的结果不一致

3.幻读(虚读): 一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录

事务的传播行为:

传播行为说明
REQUIRED【默认】当前如果有事务,Spring就会使用该事务;否则会开始一个新事务(增、删、改)
SUPPORTS当前如果有事务,Spring就会使用该事务;否则不会开始一个新事务(查询)
MANDATORY当前如果有事务,Spring就会使用该事务;否则会抛出异常
REQUIRES_NEW当前如果有事务,把当前事务挂起,新建事务
NOT_SUPPORTED当前有事务,Spring也会在非事务环境下执行。如果当前有事务,则该事务挂起
NEVER当前有事务,Spring也会在非事务环境下执行。如果当前有事务,则抛出异常
NESTED当前有事务,则在嵌套事务中执行。如果没有,那么执行情况与REQUIRED一样

事务分为编程式事务管理和声明式事务管理:

案例;

编程式事务管理

//这是一个转账的业务,用来模拟编程式事务管理
@Service
public class AccountServiceImpl implements AccountService {
    
    @Autowired
    private AccountDao accountDao;
    TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());

    public void transfer(String out, String in, Double money) {
        
        try{
            accountDao.outMoney(out, money);
            int i=3/0;
            accountDao.inMoney(in, money);
            transactionManager.commit(status);//手动提交事务


        }catch(Exception e){
            transactionManager.rollback(status);//回滚事务
        }
       
    }
}

声明式事务管理:(注解方式)

1.创建spring 配置类

@Configuration
@ComponentScan("com.cqgcxy")
@Import({JdbcConfig.class})
//启动平台事务管理
@EnableTransactionManagement
public class SpringConfiguration {
    
}

2.业务层代码实现

@Service
public class AccountServiceImpl implements AccountService {
    
    @Autowired
    private AccountDao accountDao;

    @Transactional
    public void transfer(String out, String in, Double money) {
        
        
            accountDao.outMoney(out, money);
            int i=3/0;
            accountDao.inMoney(in, money);
         
       
    }
}

这样就实现了在处理业务时发生错误,使其转账不会出现这个人已经转出去了,那个人还没收到的情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值