AOP 概述及相关基础知识

一、AOP 概述

AOP 是 Aspect Oriented Programing 的简称,面向切面的编码;

AOP 的工作重心是如何将增强应用到目标对象的连接点上:

        第一,通过切点和增强定位到连接点上;

        第二,在增强中编写切面的代码;

 

1.1、连接点 - Joinpoint

Spring 仅支持方法的连接点;

连接点由两个个信息确定:

       (1)一是用方法表示的程序 执行点

(2)二是用相对位置表示的 方位

如在 Test.foo() 方法执行前的连接点,执行点是 Test.foo(),方位是该方法执行前的位置;

 

1.2、切点 - Pointcut

切点可以用来定位连接点;

在 Spring 中,切点通过 org.springframework.aop.Pointcut 接口进行描述,使用类和方法作为连接点的查询条件,Spring AOP 的规则解析引擎负责解析切点所设定的查询条件,找到连接点,准备的说是 执行点;

Spring 通过 org.springframework.aop.Pointcut 接口描述切点:

  • ClassFilter:定位到某些特定类上;
  • MethodMatcher:定位到某些特定的方法上;

 

1.3、增强 - Advice

增强是织入目标类连接点上的 一段程序代码

在 Spring 中,增强还拥有一个和连接点有关的信息,就是 执行点的方位

如 BeforeAdvice、AfterReturningAdvice、ThrowsAdvice 等;

 

1.4、目标对象 - Target

增强逻辑的织入目标类;

 

1.5、引介 - Introduction

引介是一种特殊的增强,它可以为类添加一些属性和方法,比如间接的帮业务类实现某个接口;

 

1.6、织入 - Weaving

织入就是将增强或者引介添加到目标类的具体连接点上的过程;

(1)编译期织入,要求使用特殊的 Java 编译器;

(2)类装载期织入,要求使用特殊的类装载器;

(3)动态代理织入,在运行期为目标类添加增强生成子类的方式;

Spring 采用的是 动态代理织入,而 AspectJ 采用 编译期织入和类装载期织入

 

1.7、代理 - Proxy

一个类被 AOP 织入增强后,会产生一个结果类,它是 融合了原类和增强逻辑的代理类;

 

1.8、切面 - Aspect

切面由 切点增强(引介)组成;

包含了 横切代码 和 连接点 信息;

 

二、基础知识 - 动态代理技术

Spring AOP 使用动态代理技术在运行期织入增强的代码,它使用了两种代理机制:

(1)一种是基于 JDK 的动态代理;

(2)一种是基于 CGLib 的动态代理;

之所以需要两种动态代理机制,是因为 JDK 本身只提供接口的代理,而不支持类的代理;

二者的区别可以参考我之前的文章:Spring AOP 两种动态代理机制

 

JDK 的动态代理主要涉及 java.lang.reflect 包中的两个类:

(1)Proxy ;

(2)InvocationHandler(是一个接口);

 

原始的 AOP 有三个问题:

(1)目标类的所有方法都添加了性能监视横切逻辑,但是我们只希望对业务类中的某些特定的方法添加横切逻辑;

(2)通过硬编码的方式指定了织入横切逻辑的织入点,及在方法开始前还是结束前织入代码;

(3)手工编写代理实例的创建过程,为不同的类创建代理时,需要分别编写相应的创建代码,无法做到通用;

Spring AOP 则是通过 Pointcut 指定哪些类的哪些方法需要织入横切逻辑,通过 Advice 描述横切逻辑和方法的具体织入方位;其通过 切面 Advisor 将 Pointcut 和 Advice 组装起来,这样就可以利用 JDK 和 CGLib 采用统一的方式为目标对象创建织入切面的代理对象了;

 

 

三、问题

3.1、spring AOP无法拦截内部方法调用(方法 A 内部调用了本类的方法 B,B没有得到增强)?

方法内部之间调用的时候,不会使用被增强的代理类,而是直接调用未被增强的原类方法;

解决方法有很多,将增强类写入原类中属性中,然后使用该属性调用 B 方法,或者使用如下方法:

(1)配置文件添加 expose-proxy 属性,值为 true;

        <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true">

(2)内部调用的地方使用,使用前先判断 AopContext.currentProxy() 是否存在;

        ((类名) AopContext.currentProxy()).方法名

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值