Spring 框架 -- AOP (持续完善中)







Spring AOP

AOP:[Aspect Oriented Programming] 面向切面编程。

我们很容易想到OOP, AOP是OOP 的延伸,我们从如下角度来思考:

①. OOP 从 “各司其职”的角度为划分"对象",每个对象都有特定的功能, 比如:

  • StudentService 对象包含如下的方法
    • add 方法
      • 核心业务逻辑, 做数据的添加操作
      • 非核心业务逻辑, 日志、权限审核、事务、异常处理
    • update 方法
      • 核心业务逻辑, 做数据的更新操作
      • 非核心业务逻辑, 日志、权限审核、事务、异常处理
    • findAll 方法
      • 核心业务逻辑, 做数据的查询操作
      • 非核心业务逻辑, 日志、权限审核、事务、异常处理

②. AOP 是基于OOP的基础之上,进一步去“切割”非核心业务逻辑,把非核心逻辑当做一个切面,可以按需注入到目标对象中。



AOP的核心概念


切面[aspect]

只是一个统称,它相当于是 Advice + PointCut 的综合体,也就是匹配规则 + 增强代码 合在一起才叫 一个 切面。

如何去开发一个切面?
写一个类如下:

@Aspect    //表明我是一个“切面”
@Component  //切面 也要是一个 JavaBean, 需要被IOC容器管理
public class LogAdvice {
    
    //定义你自己需要添加的增强代码
    @PointCut(value="execution(.... .... .... ....)")
    public void init() {
        //...
        //...
    }
    
    @Before(value="init()")
    public void beforeLog() {
        
        //....
    }
}


代码增强[advice]

它是切面的代码载体,也就是我们要书写的代码,如:日志、事务、异常处理等 ,也就是 一个又一个类型,一般叫 xxxAdvice、xxxAspect, 如: LogAdvice.java



切入点[PointCut]

它是一组规则【一般采用正则表达式】,它用来配置 Advice, 在符合我们定义的规则的情况下,注入到目标业务对象的方法中。【它可以定位到 目标对象的目标方法中】 其语法为:

@PointCut(value=“execution(pubilc * 包名.类名.方法名(…))”)

注:一个 PointCut 有多个连接点【5个】



连接点[JoinPoint]

当代码增强匹配到目标方法后,我们的增强代码的执行时机 , 这个执行时机有:

  • 在目标方法执行之前, before => @Before
  • 在目标方法执行之后,after => @After
  • 在目录方法执行过程中招聘了异常, afterThrowing => @AfterThrowing
  • 在目录方法返回之后【相当于finally块】执行, afterReturing => @AfterReturning
  • 环绕 [aroud],也就是上面4种的综合体, aroud => @Around


织入[Weaving]

它是表达织入的过程,把增强代码注入到目标方法中的过程叫织入, 它是一个动作。



AOP的开发步骤

  1. 写一个 切面类,打上两个注解: @Aspect 和 @Component 注解
package com.hc.advice;

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

/***********************
 * 日志代码增强
 */
@Aspect
@Component
public class LogAdvice {

    //定义了匹配目标对象的规则【正则表达式】
    @Pointcut("execution(public * com.hc.service.impl.StudentServiceImpl.*(..))")
    public void aop_ruler(){
        //nothing!
    }

    //定义在目标方法执行之前要记的日志
    @Before(value = "aop_ruler()") //在调用PointCut规则匹配成功后的目标方法之前调用此方法
    public void pre_target(JoinPoint jp) {
        //通过 JointPoint 来获取目标对象、目标方法
        String targetClass = jp.getTarget().getClass().getSimpleName();
        String mName = jp.getSignature().getName(); //方法名
        Object[] args = jp.getArgs(); //获取参数
        //
        System.out.printf("--before: 调用[%s]对象的[%s]方法\n",targetClass,mName);
        if(args != null) {
            //说明方法有参数
            System.out.println("\t --before: 参数值有(");
            for(Object arg : args) {
                System.out.printf("\t\t%s  ",arg);
            }
            System.out.println(")");
        }
    }

    @After("execution(public * com.hc.service.impl.StudentServiceImpl.findAll(..))")
    public void after_target(JoinPoint jp) {
        System.out.printf("--after: 【%s】执行了\n",jp.getSignature().getName());
    }

    //目标方法出现异常时才会调用此方法
    @AfterThrowing(value="aop_ruler()",throwing = "e")
    public void after_throwing(JoinPoint jp, Throwable e) {
        System.out.println("--afterThrowing,表示目标方法出异常了:");
        System.out.println("--afterThrowing,"+e);
    }

    /******
     * 这个方法是相当于目标已经返回后【1.正常返回,2.异常返回】,再执行
     * @param jp
     * @param result
     */
    @AfterReturning(value = "aop_ruler()",returning = "result")
    public void after_return(JoinPoint jp, Object result) {
        System.out.println("--afterReturning: 目标方法返回后执行此方法,结果是:"+result);
    }
}
  1. 在pom.xml中,加入 spring-aspects 的依赖
<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-aspects</artifactId>
     <version>${spring.version}</version>
</dependency>
  1. AppConfig.java中,添加打开AOP的注解开头
@Configuration   //表示这是一个spring 注解配置类
@ComponentScan({"com.hc.service.impl","com.hc.dao.impl"
                    ,"com.hc.advice"})
@PropertySource(value = "classpath:db.properties")   //表示读取指定的属性文件,
                        // 并存放在Environment对象中
@EnableAspectJAutoProxy  //启用 AOP 机制
public class AppConfig {
    
}
  1. 定义一个方法,使用 @Before, @After, @AfterThrowing, @AfterReturning, @Around注解来定义PointCut
  1. 单元测试


AOP相关的注解

  • @EnableAspectJAutoProxy
  • @ Aspect
  • @Component
  • @PointCut
  • @Before
  • @After
  • @AfterThrowing
  • @AfterReturning
  • @Around


AOP相关的API

  • JoinPoint 连接点
  • Signature 方法签名
  • ProceedingJoinPoint 环绕连接点


AOP 的原理

动态代理, Spring支持两种方式

  1. 基于JDK自带的代理生成机制,它要求目标对象要有实现的接口,否则,不能生成代理对象
  2. 基于第三方类库 CGLIB 来生成代理,它不要求目标对象要实现接口。



Note:
欢迎点赞,留言,转载请在文章页面明显位置给出原文链接
知者,感谢您在茫茫人海中阅读了我的文章
没有个性 哪来的签名!
详情请关注点我
持续更新中

© 2020 09 - Guyu.com | 【版权所有 侵权必究】
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值