aop原理及理解
- 概念
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原理及理解的更多相关文章
- Spring AOP 原理的理解
>AOP基本概念 1)通知(Advice):织入到目标类连接点上的一段程序代码.通知分为五种类型: - Before:在方法被调用之前调用 - After:在方法完成后调用通知,无论方法是否执行 ...
- Spring学习总结(1)——Spring AOP的概念理解
1.我所知道的aop 初看aop,上来就是一大堆术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等.一下子让你不知所措,心想着:怪不得 很多人都和我说aop多难多难 .当我看进去 ...
- SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对比注解方式的优缺点)
接上一篇 SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP 本文采用强制的CGLB代理方式 Security ...
- (转存)面向切面编程(AOP)的理解
面向切面编程(AOP)的理解 标签: aop编程 2010-06-14 20:17 45894人阅读 评论(11) 收藏 举报 分类: Spring(9) 在传统的编写业务逻辑处理代码时,我们通常 ...
- Spring之AOP原理、代码、使用详解(XML配置方式)
Spring 的两大核心,一是IOC,另一个是AOP,本博客从原理.AOP代码以及AOP使用三个方向来讲AOP.先给出一张AOP相关的结构图,可以放大查看. 一.Spring AOP 接口设计 1.P ...
- coding++:Spring 中的 AOP 原理
为什么使用 AOP 如下场景: 现在有一个情景: 我们要把大象放进冰箱,步骤为:打开冰箱->放入大象->关闭冰箱 如果再把大象拿出来,步骤为:打开冰箱->拿出大象->关闭冰箱 ...
- Atitit 泛型原理与理解attilax总结
Atitit 泛型原理与理解attilax总结 1. 泛型历史11.1.1. 由来11.2. 为什么需要泛型,类型安全21.3. 7.泛型的好处22. 泛型的机制编辑22.1.1. 机制32.1.2. ...
- spring ioc aop 原理
spring ioc aop 原理 spring ioc aop 的原理 spring的IoC容器是spring的核心,spring AOP是spring框架的重要组成部分. 在传统的程序设计中,当调 ...
- 从tcp原理角度理解Broken pipe和Connection reset by peer的区别
从tcp原理角度理解Broken pipe和Connection reset by peer的区别 http://lovestblog.cn/blog/2014/05/20/tcp-broken-pi ...
随机推荐
- 【C++】关键字inline
1. 引入inline关键字的原因 在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数. 栈空间就是指放置程序的局部数据(也就是 ...
- IDEA编译时出现 Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8
错误如下 检查下面几个地方设置是否一致... 1.Project Structure下(File->Project Structure...) Sources选项卡->Languate l ...
- LeetCode——17. Letter Combinations of a Phone Number
一.题目链接: https://leetcode.com/problems/letter-combinations-of-a-phone-number/ 二.题目大意: 给定一段数字字符串,其中每个数 ...
- 2016-08-15T16:00:00.000Z 格式转换成yyyy-MM-dd HH:mm:ss格式
public static String UTCStringtODefaultString(String UTCString) { try { if (CommonUtils.notNullAndEm ...
- 理解OpenShift(5):从 Docker Volume 到 OpenShift Persistent Volume
理解OpenShift(1):网络之 Router 和 Route 理解OpenShift(2):网络之 DNS(域名服务) 理解OpenShift(3):网络之 SDN 理解OpenShift(4) ...
- js-语法
js中slice方法(转) 1.String.slice(start,end)returns a string containing a slice, or substring, of string. ...
- 基于ssd的手势识别模型(object detection api方式)
[Tensorflow]Object Detection API-训练自己的手势识别模型 1. 安装tensorflow以及下载object detection api 1.安装tensorflow: ...
- [java 2019-04-09] 代码生成word文档中的表格嵌套问题
public static void createContent3(Date adtStart, Date adtEnd, Map<String, Object> aMap,Map< ...
- efcore migration
实体------->migration------->db ---------------------------------------------------------------- ...
- Spring MVC配置实例
1.下载Jar文件,添加到项目 lib文件夹中. 使用eclipse新建 Web 项目.下载导入相关的 jar 和 Tomcat.我的java版本是JDK1.8 对应的 Tomcat 版本是 8.0. ...