• 概念

Aspect Oriented Programming,面向切面编程,实际上它是一个规范、一种设计思路,总之是抽象的。

先上图

  • 使用目的

从项目结构上来说

对业务逻辑的各个部分进行隔离,降低业务逻辑的耦合度

从开发的角度上说

减少重复编码,提高程序的可重用性,提高了开发的效率

总结简单的讲:就是那些与业务无关,却为业务模块所共同调用的逻辑封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

  • 使用场景

日志记录,性能统计,安全控制,事务处理,异常处理等

  • 概念理解(仅指java中)

先上图

圆柱:原有的业务流程,从上至下执行

蓝色面:即切面,为指定的业务流程增加功能;交界处即切点,意味着将增加的功能插入到指定位置(单位是方法)

AOP核心概念

1、横切关注点

对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点,即公共封装的业务逻辑,如日志记录

2、切面(aspect)

类是对物体特征的抽象,切面就是对横切关注点的抽象

3、连接点(joinpoint)

被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器,在此不做深究

4、切入点(pointcut)

对连接点进行拦截的定义

5、通知(advice)

所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

6、目标对象

代理的目标对象

7、织入(weave)

将切面应用到目标对象并导致代理对象创建的过程

8、引入(introduction)

在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

  • spring aop实现方法

通常我们采用2种

基于注解

/**
* 系统服务组件Aspect切面Bean*/
//声明这是一个组件
@Component
//声明这是一个切面Bean
@Aspect
public class ServiceAspect { private final static Log log = LogFactory.getLog(ServiceAspect.class); //配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
@Pointcut("execution(* com.hyq.aop..*(..))")
public void aspect(){ } /*
* 配置前置通知,使用在方法aspect()上注册的切入点
* 同时接受JoinPoint切入点对象,可以没有该参数
*/
@Before("aspect()")
public void before(JoinPoint joinPoint){
System.out.println("执行before.....");
} //配置后置通知,使用在方法aspect()上注册的切入点
@After("aspect()")
public void after(JoinPoint joinPoint){
System.out.println("执行after.....");
} //配置环绕通知,使用在方法aspect()上注册的切入点
@Around("aspect()")
public void around(JoinPoint joinPoint){
long start = System.currentTimeMillis();
try {
((ProceedingJoinPoint) joinPoint).proceed();
long end = System.currentTimeMillis();
if(log.isInfoEnabled()){
log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
}
} catch (Throwable e) {
long end = System.currentTimeMillis();
if(log.isInfoEnabled()){
log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
}
}
} //配置后置返回通知,使用在方法aspect()上注册的切入点
@AfterReturning("aspect()")
public void afterReturn(JoinPoint joinPoint){
if(log.isInfoEnabled()){
log.info("afterReturn " + joinPoint);
}
} //配置抛出异常后通知,使用在方法aspect()上注册的切入点
@AfterThrowing(pointcut="aspect()", throwing="ex")
public void afterThrow(JoinPoint joinPoint, Exception ex){
if(log.isInfoEnabled()){
log.info("afterThrow " + joinPoint + "\t" + ex.getMessage());
}
} }

基于配置

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--<context:component-scan base-package=""--> <!-- 定义目标对象 -->
<bean name="productDao" class="com.xxx.spring.springAop.dao.daoimp.ProductDaoImpl" /> <!-- 定义切面 -->
<bean name="myAspectXML" class="com.xxx.spring.springAop.AspectJ.MyAspectXML" />
<!-- 配置AOP 切面 -->
<aop:config>
<!-- 定义切点函数 -->
<aop:pointcut id="pointcut" expression="execution(* com.xxx.spring.springAop.dao.ProductDao.add(..))" /> <!-- 定义其他切点函数 -->
<aop:pointcut id="delPointcut" expression="execution(* com.xxx.spring.springAop.dao.ProductDao.delete(..))" /> <!-- 定义通知 order 定义优先级,值越小优先级越大-->
<aop:aspect ref="myAspectXML" order="0">
<!-- 定义通知
method 指定通知方法名,必须与MyAspectXML中的相同
pointcut 指定切点函数
-->
<aop:before method="before" pointcut-ref="pointcut" /> <!-- 后置通知 returning="returnVal" 定义返回值 必须与类中声明的名称一样-->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut" returning="returnVal" /> <!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut" /> <!--异常通知 throwing="throwable" 指定异常通知错误信息变量,必须与类中声明的名称一样-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="throwable"/> <!--
method : 通知的方法(最终通知)
pointcut-ref : 通知应用到的切点方法
-->
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>

重点介绍下pointcut(切入点) expression表达式解析及配置

方法参数匹配

args()

@args()

方法描述匹配

execution()

当前AOP代理对象类型匹配

this()

目标类匹配

target()

@target()

within()

@within()

标有此注解的方法匹配

@annotation()

其中execution 是用的最多的,其格式为:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

ret-type-pattern,name-pattern, parameters-pattern是必须的.

ret-type-pattern:可以为*表示任何返回值,全路径的类名等. 

name-pattern:指定方法名, *代表所有 

如:set*代表以set开头的所有方法. 

parameters-pattern:指定方法参数(声明的类型),(..)代表所有参数,(*)代表一个参数 

(*,String)代表第一个参数为任何值,第二个为String类型.

更多配置细节可查看官方文档:https://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/html/aop.html#aop-introduction

  • 原理分析

简单的讲,即使用jdk或cglib的动态代理功能,对目标类生成代理类,然后在代理类中调用或执行额外的新增功能。

先上图

在此推荐看https://blog.csdn.net/luanlouis/article/details/51095702

详细说明了spring aop实现的大致逻辑和机制

另外推荐https://blog.csdn.net/luanlouis/article/details/51155821

通过解析spring源码来深入理解spring aop的实现

aop原理及理解的更多相关文章

  1. Spring AOP 原理的理解

    >AOP基本概念 1)通知(Advice):织入到目标类连接点上的一段程序代码.通知分为五种类型: - Before:在方法被调用之前调用 - After:在方法完成后调用通知,无论方法是否执行 ...

  2. Spring学习总结(1)——Spring AOP的概念理解

    1.我所知道的aop 初看aop,上来就是一大堆术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等.一下子让你不知所措,心想着:怪不得 很多人都和我说aop多难多难 .当我看进去 ...

  3. SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对比注解方式的优缺点)

    接上一篇 SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP 本文采用强制的CGLB代理方式 Security ...

  4. (转存)面向切面编程(AOP)的理解

    面向切面编程(AOP)的理解 标签: aop编程 2010-06-14 20:17 45894人阅读 评论(11) 收藏 举报  分类: Spring(9)  在传统的编写业务逻辑处理代码时,我们通常 ...

  5. Spring之AOP原理、代码、使用详解(XML配置方式)

    Spring 的两大核心,一是IOC,另一个是AOP,本博客从原理.AOP代码以及AOP使用三个方向来讲AOP.先给出一张AOP相关的结构图,可以放大查看. 一.Spring AOP 接口设计 1.P ...

  6. coding++:Spring 中的 AOP 原理

    为什么使用 AOP 如下场景: 现在有一个情景: 我们要把大象放进冰箱,步骤为:打开冰箱->放入大象->关闭冰箱 如果再把大象拿出来,步骤为:打开冰箱->拿出大象->关闭冰箱 ...

  7. Atitit 泛型原理与理解attilax总结

    Atitit 泛型原理与理解attilax总结 1. 泛型历史11.1.1. 由来11.2. 为什么需要泛型,类型安全21.3. 7.泛型的好处22. 泛型的机制编辑22.1.1. 机制32.1.2. ...

  8. spring ioc aop 原理

    spring ioc aop 原理 spring ioc aop 的原理 spring的IoC容器是spring的核心,spring AOP是spring框架的重要组成部分. 在传统的程序设计中,当调 ...

  9. 从tcp原理角度理解Broken pipe和Connection reset by peer的区别

    从tcp原理角度理解Broken pipe和Connection reset by peer的区别 http://lovestblog.cn/blog/2014/05/20/tcp-broken-pi ...

随机推荐

  1. 测试开发学习进阶教程 视频&PDF

    测试开发学习进阶教程 视频&PDF,7天后失效,更多学习资料加Q群 https://pan.baidu.com/s/196KEo791NeZKyfV_E-36Uw 提取码: 41vu     ...

  2. python学习笔记八(集合)

    集合 set是一个无序的不重复元素序列. 用大括号或set()函数创建集合.注意:创建一个空集合用set(),不用{},{}用来创建空字典 basket = {'apple','orange','ap ...

  3. MapReduce论文学习

    MapReduce和区块链有什么相同的地方? 我的天哪,他俩还有相同的地方呢.我书读的少,你别骗我. 他俩还真有相同点,绝不忽悠. 他俩都有一个高大上的名字. 区块链就是一个分布式数据库,并不是什么神 ...

  4. springmvc简单的流程说明及源码分析

    框架流程图 springmvc的核心类org.springframework.web.servlet.DispatcherServlet,是一个servlet,间接继承了httpservlet;重写了 ...

  5. ssh免密登陆配置

    目录 ssh免密登陆 在A工作站上输入 B服务器上输入 登陆 ssh初次登陆询问 1.单次取消 2.ansible中增加链接参数 3.修改ansible配置参数[推荐] 4.修改服务器上的ssh_co ...

  6. n2n网络穿透内网

    目录 前言 配置 网络拓扑: 公网服务器的配置 公司电脑的配置 家里笔记本的配置 注意事项 使用n2n网络 n2n的各edge之间传输数据 补充:NAT类型 后记 前言 在家里的时候比较经常需要对公司 ...

  7. jquery 防止当前页面被Iframe嵌套,防止登录页面Iframe被嵌套

    <script type="text/javascript"> if (top.location != location) { top.location.href = ...

  8. qt qextserialport __imp_SetupDiGetDeviceRegistryPropertyW

    使用 qextserialport 编写串口助手的时候,提示找不到 __imp_SetupDiGetDeviceRegistryPropertyW,经过摸索有以下两种解决方法: 第一种: 把相应的源文 ...

  9. gogs windows

    首先安装 git,然后下载 gogs. 在gogs 文件夹位置 启动. gogs.exe web 打开浏览器,输入 127.0.0.1:3000 ,安装 gogs,注意数据库选择,仓库根目录,管理员帐 ...

  10. RDD的概念与创建

    1.RDD是整个Spark的计算基石.是分布式数据的抽象,为用户屏蔽了底层复杂的计算和映射环境 RDD是不可变的,如果需要在一个RDD上进行转换操作,则会生成一个新的RDD RDD是分区的,RDD里面 ...