《Spring篇》面向切面编程AOP

前言

了解AOP

AOP(Aspect Oriented Programming) 面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

AOP核心概念

  1. 横向关注点
    对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。

  2. 切面(aspect)
    类是对物体特征的抽象,切面就是对横切关注点的抽象。

  3. 连接点(joinpoint)
    被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。

  4. 切入点(pointcut)
    对连接点进行拦截的定义。

  5. 通知(advice)
    所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

  6. 目标对象
    代理的目标对象

  7. 织入(weave)
    将切面应用到目标对象并导致代理对象创建的过程

  8. 引入(introduction)
    在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

AOP的三种实现方式

1、基于xml配置方式

这种方式以前用的多,现在用到的项目较少,一般只有以前的老项目才会用到,所以就不再这里列举了。

2、Spring纯注解配置aop

/**
 * @program: transcribe-service
 * @description: 日志切面类
 * @author: Mr.Zhang
 * @create: 2021-11-26 11:34
 **/
@Order(1)   //指定切面的优先级,值越小,优先级越高
@Aspect //将这个类声明为一个切面:1、加入到IOC容器中,2.声明为切面
@Component
@EnableAspectJAutoProxy //使Aspect注解起作用:自动为匹配的类生成代理对象
public class LoggingAspect {

    /**
     * 声明PointCut来声明切入点表达式
     */
    @Pointcut("execution(public * com.isoftstone.manage.service.*.*(..))")      //代表任意参数
    public void declareJoinPointExpression(){
    }

    /**
     * 声明该方法是一个前置通知:在目标方法开始之前执行
     *
     * @param joinPoint
     */
    @Before("declareJoinPointExpression()")
    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("The method " + methodName + "begin with:" + args);
    }

    /**
     * 后置通知:在目标方法执行后(无论是否发生异常),执行的通知
     * 在后置通知中不能访问目标方法执行的结果
     * @param joinPoint
     */
    @After("declareJoinPointExpression()")
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " end");
    }

    /**
     * 返回通知:在方法“正常结束”之后才执行的代码,可以访问到方法的返回值
     *
     * @param joinPoint
     * @param result
     */
    @AfterReturning(value = "declareJoinPointExpression()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method "+ methodName + "end with: " + result);
    }

    /**
     * 在目标方法出现异常时会执行的代码
     * 可以访问到异常对象,且可以指定再出现特定异常时·再执行此方法
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "declareJoinPointExpression()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Exception e){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + "occurs exception:" + e);
    }

    /**
     * 和proxy的动态代理一样,可以实现上述的所有功能,测试时注释掉上面所有方法
     * 环绕通知需要携带ProceedingJoinPoint类型的参数,proceedingJoinPoint可以决定什么时候执行目标方法
     * 且必须有返回值,即目标方法的返回值
     * @param proceedingJoinPoint
     * @return
     */
    @Around(value = "declareJoinPointExpression()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
        Object result = null;
        try {
            //前置通知
            System.out.println("start");
            //执行目标方法
            result = proceedingJoinPoint.proceed();
            //返回通知
            System.out.println("return: " + result);
        }catch (Throwable throwable){
            System.out.println("Exception");
            throwable.printStackTrace();
        }

        //后置通知
        System.out.println("end");
        return result;
    }
}

3、动态代理的方式实现AOP

动态代理实现aop
测试

总结

参考相关链接
https://www.cnblogs.com/jiaweit/p/9986390.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值