Spring系列(一)——Spring AOP

AOP

AOP是什么

是一种面向切面编程的思想,传统的OOP开发中的代码逻辑是自上而下的,而这些过程会产生一些横切性问题,这些横切性的问题和我们的主业务逻辑关系不大,这些横切性问题不会影响到主逻辑实现的,但是会散落到代码的各个部分,难以维护。AOP是处理一些横切性问题,AOP的编程思想就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。使代码的重用性和开发效率更高。

AOP的应用场景

  • 日志记录
  • 权限验证
  • 事务管理

Spring AOP和AspectJ

AOP,Spring AOP,AspectJ三者之间的关系

  • AOP是一种思想。
  • SpringAop、AspectJ都是AOP的实现,Spring AOP有自己的语法,但是语法复杂,所以Spring AOP借助了AspectJ的注解,但是底层实现还是自己的。
  • Spring AOP提供了两种编程风格
@AspectJ support         ------------>利用aspectj的注解
Schema-based AOP support ----------->xml aop:config 命名空间

Spring AOP的底层技术

使用了动态代理,包含jdk动态代理和Cglib动态代理。并且在初始化时期织入。

Spring AOP的一些基本概念

  • aspect:切面

    • 在类上声明 @Aspect
    • 交给Spring管理 @Component
  • pointcut:切点

    • 连接点的集合
    • 告诉通知连接点在哪里
    • 切点表达式决定joinpoint的数量
  • joinpoint:连接点

    • 目标对象的方法
    • 要关注和增强的方法,也就是我们要作用的点。
  • weaving:织入,把代理逻辑加入到目标对象上的过程

  • target:目标对象(原始对象)

  • aop proxy: 代理对象,包含了原始对象的代码和增加后的代码的那个对象

  • advice:通知(位置 + logic)

  • advice通知类型

    • Before 连接点执行之前,无论执行正常还是异常,都会进行前置通知
    • After 连接点执行之后,无论执行正常还是异常,都会进行后置通知
    • After throwing 连接点执行抛出异常的时候,异常通知
    • After returning 连接点正常执行完成的时候,返回通知
    • Around advice 围绕连接点执行,例如方法调用。这是最有用的切面方式。around通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续加入点还是通过返回自己的返回值或抛出异常来快速建议的方法执行。环绕通知
    • 通知的优先顺序:环绕通知(前)->前置通知->目标方法->环绕通知(后)->后置通知->返回通知/异常通知
    • Spring只支持方法级的增强

Spring AOP案例

  • 创建maven项目,并引入依赖
<dependencies>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>5.0.11.RELEASE</version>
     </dependency>
     <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.9.2</version>
     </dependency>
 </dependencies>
  • 使用Java Config启用@AspectJ支持
package com.example.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class AppConfig {
}
  • 声明一个切面类
package com.example.config;

import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 声明一个切面
 * 此切面一定要交给Spring管理
 */
@Aspect
@Component
public class TxAspect {
    @Pointcut("execution(* com.example.dao.*.*(..))")
    public void pointCut(){

    }
    @After("com.example.config.TxAspect.pointCut()")
    public void after(){
        System.out.println("after...");
    }
    /**
     * before通知,在pintCut切入点前执行
     */
    @Before("com.example.config.TxAspect.pointCut()")
    public void before(){
        System.out.println("before...");
    }
    @AfterThrowing("com.example.config.TxAspect.pointCut()")
    public void doRecoveryActions(){
        System.out.println("异常");
    }
}
  • 新建dao接口和IndexDao类
package com.example.dao;

public interface Index {
    void query();
}
package com.example.dao;

import org.springframework.stereotype.Component;

@Component
public class IndexDao implements Index {
    @Override
    public void query(){
        System.out.println("dao----query");
        System.out.println(1/0);
    }
}
  • 新建测试类
package com.example.test;

import com.example.config.AppConfig;
import com.example.dao.Index;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Index dao1 =  context.getBean(Index.class);
        dao1.query();
    }
}
  • 运行结果如下

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yemuxiaweiliang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值