Spring AOP基础

IOC和AOP是Spring的两大基石,AOP(面向切面编程),是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP)。

在进行 OOP 开发时,都是基于对组件(比如类)进行开发,然后对组件进行组合,OOP 最大问题就是无法解耦组件进行开发。AOP 为开发者提供一种进行横切关注点(比如日志关注点)分离并织入的机制,把横切关注点分离,然后通过某种技术织入到系统中,从而无耦合的完成了我们的功能。

AOP世界中的居民

  • Joinpoint(连接点):指那些被拦截到的点。在Spring中只支持方法级别的连接点。
  • Pointcut(切入点):指需要配置的Joinpoint。
  • Advice(通知):指拦截到Joinpoint后要做的操作,通知分为前置通知/后置通知/异常通知/后置通知/环绕通知。
  • Aspect(切面):切入点和通知的结合。
  • Target(目标对象):需要被代理的对象。
  • Proxy(代理对象):目标对象被AOP 织入通知产生的对象。
  • Weaving(织入):指把通知应用到目标对象来创建代理对象的过程(Spring采用动态代理织入,AspectJ采用编译期织入和类装载期织入)。

AOP中的通知类型

  • 前置通知:在切入点选择的连接点处的方法之前执行的通知,该通知不影响正常程序执行流程,除非发生了异常。
  • 后置通知:在切入点选择的连接点处的方法正常执行完毕时执行的通知。
  • 返回通知:在切入点选择的连接点处的方法返回时执行的通知,不管抛没抛出异常都执行,类似于 Java 中的 finally 块。
  • 异常通知:在切入点选择的连接点处的方法抛出异常返回时执行的通知。
  • 环绕通知:环绕着在切入点选择的连接点处的方法所执行的通知,环绕通知可以在方法调用之前和之后自定义任何行为,并且可以决定是否执行连接点处的方法、替换返回值、抛出异常等等。

AOP程序示例

@Component
public interface HelloAop {
    void hello();
}

@Component
public class HelloAopImpl implements HelloAop{
    @Override
    public void hello() {
        System.out.println("---hello HelloAopImpl---");
    }
}

@Aspect
@Component
public class HelloAopAspect {
    @Before("execution(public void com.luo.aop.HelloAopImpl.hello())")
    public void beforeAdvice(JoinPoint point) {
        String methodName = point.getSignature().getName();
        System.out.println("beforeAdvice: " + methodName);
    }

    @After("execution(public void com.luo.aop.HelloAopImpl.hello())")
    public void afterAdvice(JoinPoint point) {
        String methodName = point.getSignature().getName();
        System.out.println("afterAdvice: " + methodName);
    }

    @AfterThrowing("execution(public void com.luo.aop.HelloAopImpl.hello())")
    public void afterThrowingAdvice(JoinPoint point) {
        String methodName = point.getSignature().getName();
        System.out.println("afterThrowingAdvice: " + methodName);
    }

    @AfterReturning("execution(public void com.luo.aop.HelloAopImpl.hello())")
    public void afterReturningAdvice(JoinPoint point) {
        String methodName = point.getSignature().getName();
        System.out.println("afterReturningAdvice: " + methodName);
    }

    @Around("execution(public void com.luo.aop.HelloAopImpl.hello())")
    public Object aroundAdvice(ProceedingJoinPoint point) {
        Object result = null;

        // 环绕通知(前通知)
        System.out.println("aroundAdvice start...");
        try {
            // 前置通知
            result = point.proceed(); // 目标方法执行
        } catch (Throwable throwable) {
            // 异常通知
            throwable.printStackTrace();
        }
        // 环绕通知(后通知)
        System.out.println("aroundAdvice end...");
        // 后置通知
        // 返回通知

        return result;
    }
}

public static void main(String[] args) {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("springConfig.xml");

    HelloAop helloAop = ctx.getBean(HelloAop.class);

    helloAop.hello();
}

spring配置文件:

<!-- 自动扫描 -->
<context:component-scan base-package="com.luo.aop"/>

<!-- 使用AspjectJ自动生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
AOP通知输出结果

指定切面优先级

在同一个连接点上应用不止一个切面时, 除非明确指定, 否则它们的优先级是不确定的。切面的优先级可以通过实现 Ordered 接口或利用 @Order 注解指定。实现 Ordered 接口, getOrder() 方法的返回值越小, 优先级越高.若使用 @Order 注解, 序号出现在注解中。

@Aspect
@Order(0)
@Component
public class HelloAspect2 { }

@Aspect
@Order(1)
@Component
public class HelloAspect { }

参考资料:

  1. 《Spring揭秘》AOP章节
  2. Spring学习之AOP总结帖
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容

  • AOP实现可分为两类(按AOP框架修改源代码的时机): 静态AOP实现:AOP框架在编译阶段对程序进行修改,即实现...
    数独题阅读 2,317评论 0 22
  • **** AOP 面向切面编程 底层原理 代理!!! 今天AOP课程1、 Spring 传统 AOP2、 Spri...
    luweicheng24阅读 1,365评论 0 1
  • 本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 ...
    谢随安阅读 3,146评论 0 9
  • 在KTV拿手机照明,让小莹莹给我看手相,结论如下,感情纠结,锻炼身体。实在是无奈又无从反驳。莹莹同学是一个说话铿锵...
    S苏苏S阅读 460评论 0 1
  • 做学生十余年,遇到的老师各种各样。 而今的年龄也到了,我的同学再过几年就是老师了这样一个情况。 我不知道怎么定义老...
    静好_阅读 9,255评论 4 23