• 概念

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. 猜测的rpc负载均衡原理,基于dubbo的架构

    集群层(Cluster):封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster.Directory.Router和LoadBalance.将多个服务提供方组 ...

  2. python解决四舍五入问题

    小数问题是计算机编程中大部分语言都会遇到的问题,尤其是在内容中涉及到评分.金额计算等等,本人一般在解决需求中固定小数位的数字计算时,都会先将其放大整10的倍数至整数,然后计算.存储,只有在显示的时候再 ...

  3. centos7 Ruby环境变量配置

    ruby安装参考博客:https://blog.csdn.net/yelllowcong/article/details/78362370  (Redis之集群redis-trib.rb环境的搭建-y ...

  4. Arrays和String单元测试

    20175227张雪莹 2018-2019-2 <Java程序设计> Arrays和String单元测试 要求 在IDEA中以TDD的方式对String类和Arrays类进行学习 测试相关 ...

  5. [转][C#]ImageHelper

    { internal static class ImageHelper { public static Bitmap CloneBitmap(Image source) { if (source == ...

  6. Centos7之系统优化

    优化条目: 修改ip地址.网关.主机名.DNS等 关闭selinux,清空iptables 添加普通用户并进行sudo授权管理 更新yum源及必要软件安装 定时自动更新服务器时间 精简开机自启动服务 ...

  7. To be taught if i am fortunate

    此博客算是我自娱自乐的海洋球池吧. 由于我十分的菜并且文笔拙劣,所以您可能并不能在这找到什么有用的信息或者好玩的东西(或者exciting的内容). 如果您能指出我的一些错误,我将十分感激.

  8. winform界面特效470多例

    一共470多例winform 界面特效的源码. 实例030 窗口颜色的渐变 实例说明 在程序设计时,可以通过设置窗体的BackColor属性来改变窗口的背景颜色.但是这个属性改变后整个窗体的客户区都会 ...

  9. 事件&表达式

    typeFaqs.ForEach(async p => { var results = await  ; p.Results = results; }); https://stackoverfl ...

  10. JS面试Q&A(续2): Rest parameter,Arrow function 等

    rest parameter 和 Destructuring assignment. function fun1(...theArgs) { console.log(theArgs.length);} ...