栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring 框架实战: AOP

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring 框架实战: AOP

1 概述

Spring 的切面编程由 AspectJ 提供支持.

AOP 需要了解的基础:

  1. 使用 @Aspect 声明一个切面.
  2. @After, @Before, @Around 定义 建言(advice); 这 3 个注解的参数 就是 切点(PointCut) , 所谓 切点 其实就是一个 拦截规则(可以由注解定义, 也可以由方法规则定义).
  3. 可以把 切点 用 @PonitCut 来定义, 然后放到 @After, @Before, @Around 当参数, 这样可以复用切点.
  4. 符合 拦截条件 的每一处 也是 连接点(JoinPoint).
2 AOP 示例

下面演示一下两种定义切点的方式:
基于自定义注解的切点 和 基于方法规则的切点.

本示例用到的代码已经放在 GitHub 上.

2.1 自定义一个切点注解 @MyAction

自定义一个注解 @MyAction 用来标记切点的位置:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface MyAction {
    String name();
}

注解本身没有功能, 就和 xml 一样.
注解和 xml 都是元数据(解释数据的数据), 也就是所谓的配置.
注解需要被其他程序解析才有用.
MyAction 在 切面定义 被解析成切点.

2.2 定义两个方法用来测试测点

定义两个方法, 在这两个方法上测试切点:

@Service
public class TestService {
    public void method1() {
        System.out.println("execute first method..");
    }

    @MyAction(name = "自定义注解")
    public void method2() {
        System.out.println("execute second method..");
    }
}

2.3 定义一个切面
@Aspect // 声明一个切面
@Component
public class TestAspect {
    // @Pointcut 用来定义切点. 这里把带有 @MyAction 注解的方法 视为切点.
    @Pointcut("@annotation(cn.mitrecx.learn2aop.aop.MyAction)")
    public void annotationPointCut() {
    }

    
    // @After("@annotation(cn.mitrecx.learn2aop.aop.MyAction)") // 和下面的 @After 等效
    @After("annotationPointCut()")
    public void afterExecution(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MyAction action = method.getAnnotation(MyAction.class);
        System.out.println("After(注解式拦截): " + action.name());
    }

    
    @Before("execution(* cn.mitrecx.learn2aop.aop.TestService.*(..))")
    public void beforeExecution(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println("Before(方法规则式拦截): " + method.getName());
    }
}

上面 @Before 使用 方法规则式切点 不太好,它会导致 代码逻辑不清晰.
因为我们无法直接从 TestService 类里的方法 看出方法 “篡改” 了(被加了beforeExecution()逻辑).

2.4 配置类
@Configuration
@ComponentScan("cn.mitrecx.learn2aop.aop")
@EnableAspectJAutoProxy
public class AopConfig {
}
2.5 主程序
public class MyApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AopConfig.class);

        TestService testService = context.getBean(TestService.class);

        testService.method1();
        System.out.println("---------");
        testService.method2();

        context.close();
    }
}

运行结果:

Before(方法规则式拦截): method1
execute first method..
---------
Before(方法规则式拦截): method2
execute second method..
After(注解式拦截): 自定义注解

结果显示, 两个方法规则式切点(methed1, methed2) 的 @Before 建言 在切点方法执行前 被执行;
注解式切点(methed2) 的 @After 建言 在切点方法执行后 被执行.

注意:
这里只是为演示两种定义切点的方式.
个人建议只使用 注解式切点, 因为它看起来更清晰.

Reference

[1]. Spring Boot 实战 - 汪云飞

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/297851.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号