Spring_AOP_01——概念讲解

该文主要讲Spring AOP的一些概念,不会细讲如何使用AOP。
关于AOP的使用,可以参考文末链接。

AOP 概述

AOP是Spring框架的另一个基本组成部分。这一次我们就探讨一下Spring的这一重要特性。面向切面(Aspect Oriented Programming)

需要明确的是,AOP并不是Spring独有,AspectJ也实现了AOP的功能。AOP和OOP一样,是一种编程范式。而Spring实现的AOP功能比较经典。

实现AOP使用的是代理模式。通过对需要切入类的包装和增强,创建代理类。从而实现切入到执行过程中的作用。

代理主要分为两种方式:

  • 静态代理,基本的代理方式,AspectJ使用。
  • 动态代理,Spring使用的代理方式,使用了JDK和CGLIB的代理方式。

具体的代理实现AOP的原理,在下一期细讲。


什么是AOP?
AOP(Aspect Oriented Programming)面向切面编程,可以说是OOP(Object Oriented Programming)面向对象编程的补充和完善。

具体来说,AOP是通过 预编译方式运行时的动态代理 实现程序功能的统一维护的一种技术。AOP是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。

为什么要用AOP?
随着开发的系统越来越复杂,传统OOP程序会出现一些不自然的现象。核心业务中总掺杂一些不相关的业务。例如:日志记录,权限验证,事务控制,性能检测等等。这些功能模块可以说跟核心业务并无关系,而且核心业务也不关心他们。

这些场景就是一些分散的对象,涉及到了公共的行为。OOP在这方面显得无能为力。
这里要说一下,虽然可以使用继承来对公共行为做抽象,但是继承是一个纵向的关系,并且是强耦合的一种方式。有时候子类并不需要这个行为,而在很多情况下,需要这样行为的类之间根本就毫无关系。
如果非要使用这种方式,不仅会导致大量的重复代码,维护起来也是相当麻烦的一件事情,一点都不优雅。

而AOP引入了一种 "横切" 的技术,它是一种横向的关系。AOP使得我们可以把一些公共行为抽离出来,并且把这些行为,横向地插入到业务代码执行的过程中间。所以称之为 切面(Aspect)
这些横切进去的行为与具体业务无关,又嵌入到了业务模块的执行逻辑流程中,共同封装起来。便于减少重复代码,也降低了耦合度。利于系统的扩展性和可维护性。

可以用一张图简单的说明AOP的作用

AOP


AOP的功能

  • 用于横切关注点的分离 和 织入横切关注点到系统。例如日志,权限等
  • 对OOP的完善
  • 降低组件和模块之间的耦合性
  • 使得系统更易于扩展
  • 分离关注点可以获得组件更好的复用


AOP的使用场景

  • Authentication 权限
  • Caching 缓存
  • Context passing 内容传递
  • Error handling 错误处理
  • Lazy loading 懒加载
  • Debugging 调试
  • logging, tracing, profiling and monitoring 记录跟踪 优化 校准
  • Performance optimization 性能优化
  • Persistence 持久化
  • Resource pooling 资源池
  • Synchronization 同步
  • Transactions 事务



AOP 核心概念

切面(Aspect)
切面是一个关注点,或者说希望抽象出来的功能 的模块化。这个关注点或者功能可以横切多个对象。对应代码中,就是声明出来切面的类和其中的所有逻辑。

连接点(JoinPoint)
连接点是指在程序中某个特定的点,通过这个点来和切面建立连接,将切面的功能组合进去。他表示了可以组合 Advice 的位置。
也就连接点,是允许你执行通知的地方。在Spring中允许的通知有五种(接下来讲)。AspectJ还允许在构造器和属性注入时执行通知。
简单来说,在Spring中,方法的前前后后都是连接点,


通知(Advice)
通知是在切面上某个连接点上执行的特定操作。也就是我们抽离出来公共功能代码的逻辑部分。Spring切面中支持五种通知:

  • 前置通知(Before)在目标方法,或者说切点被调用前执行的通知。
  • 后置通知(After)在切点被调用后执行。
  • 返回通知(After-returning)在切点执行成功并返回以后执行
  • 异常通知(After-throwing)在方法抛出异常之后执行
  • 环绕通知(Around)包围一个连接点,在被通知的方法之前和之后执行。(内部调用 proceed() 来执行通知方法)

关于通知的执行优先级。
在不同的切面中,如果有多个通知需要在同一个切点函数指定的方法上执行,那么将会按照在代码中定义的顺序依次执行。

切点(PointCut)
简单来说,切点是匹配连接点的表达式或者说断言。
在上面切面概念的基础上,我们知道,方法的前后都可以是连接点,但我们并不希望在所有这些地方都执行通知,我们需要一个自己定义执行通知的地方。也就是切点。
通过切点的定义,就是让我们可以筛选出我们想要拦截的方法。

引入(Introduction)
在不修改代码的前提下,引入可以在 运行期 动态地为类添加一些方法或者字段。
也就是把切面应用到目标类中。

目标对象(Target Object)
引入中提到的目标类,也就是被通知的对象(具体的业务逻辑)。
目标对象可以在不关心切面的情况下被引入切面的新功能,实现了功能的解耦。

AOP代理(AOP Proxy)
AOP代理指AOP框架创建的,对象和切面的契约,也可以说是切面实现的方式。
事实上,一般AOP是通过代理的方式实现的。(代理又分为静态代理和动态代理,Spring使用的是动态代理)
AOP代理的目的,就是将切面织入到目标对象。

织入(Wearving)
把切面应用到目标对象,来创建代理对象的过程。Spring采用的是运行时织入,具体有两种方式JDK和CGLIB。AspectJ采用的是编译期织入。(这个下一期AOP原理分析时细讲)

以下是Spring使用注解方式实现AOP的简单例子(当然还可以使用xml配置的方式实现AOP)

使用Spring的AOP支持需要引入Spring-aspect的包,如果要启用注解支持,还需要添加AspectJ类库。

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.0.1.RELEASE</version>
    </dependency>

    <!-- aspectJ -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.8.10</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.10</version>
    </dependency>

/**
 * @Author Antony
 * @Since 2017/11/30 16:35
 */
@Aspect
@Component
public class SychLockAspect {    //该类就是切面

    private static final Logger logger = LoggerFactory.getLogger(SychLockAspect.class);

    @Pointcut("execution (* com.antony.service.*.*(..))")    //这是切点表达式
    public void SychLockMethod(){}  //该方法体就是通知,内部是通知的逻辑,同时可以有before after , around 等 5种通知动作。

    @Before(value = "SychLockMethod()")
    public void beforeAspect(JoinPoint joinPoint){
        String sychKey = getSychKey(joinPoint);
        logger.info("sychKey={}", sychKey);
        logger.info("AspectBefore......");

    }


    @After(value = "SychLockMethod()")
    public void afterAspect(JoinPoint joinPoint){
        String sychKey = getSychKey(joinPoint);
        logger.info("sychKey={}", sychKey);
        logger.info("AspectAfter......");
    }


    @Around(value = "SychLockMethod()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("Around before...");
        proceedingJoinPoint.proceed();
        System.out.println("Around After...");
    }
}



Spring AOP 的支持

Spring中的AOP代理,由Spring IOC 容器负责生成和管理。其依赖关系也由IOC容器负责管理。AOP代理可以直接使用容器中的其他Bean实例作为目标,这种关系可以由IOC容器的依赖注入提供。

Spring 默认使用JDK动态代理来创建AOP代理类。Spring目前仅支持将方法调用作为连接点(JoinPoint),如果需要把堆成员变量的访问和更新页作为增强处理的连接点,则可以考虑使用AspectJ。

Spring侧重于AOP实现和IOC容器之间的整合。


Spring 框架对AOP的使用
Spring 事务处理
SpringMVC(例如@ControllerAdvice)
Spring Security
(由于对Spring的各个功能模块都还没有完整的了解,目前已知的是这些,应该还有更多,后续补充)



(如果有什么错误或者建议,欢迎留言指出)
(本文内容是对各个知识点的转载整理,用于个人技术沉淀,以及大家学习交流用)


参考资料:
关于SpringAOP你该知晓的一切
Spring之AOP-简书(主要是AOP基本概念和如何使用AOP)
AOP低层实现——JDK和CGLIB的动态代理

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