Aop的基本介绍
基本概念
- 通知
就是你想要的功能,也就是我们常说的安全、事物、日志等。先定义好这些,然后再想用的地方用一下。包含Aspect的一段处理代码
注意:其实这些功能(通知)并不是我们业务逻辑所必须的,只是为了安全,输出信息,或者其他的原因,总之是为了方便我们对项目维护而增加的操作,一般我们会把这些功能封装成相关的方法,但是我们又不想这些功能直接入侵我们的正常业务代码,因为这样会增加关注度并且污染我们的业务逻辑,所以我们就用切面的思想来很好解决这个问题
- 连接点
就是spring允许你加 通知(Advice)的地方,那可就真多了,基本每个方法的前、后(两者都有也行),或抛出异常时都可以是连接点,spring一般只支持方法连接点,除非引入其他的aop框架才可以实现更细粒度的连接点。其他如AspectJ还可以让你在构造器或属性注入时都行,不过那不是咱们关注的,只要记住,和方法有关的前前后后都是连接点
- 切入点
在上面说的连接点的基础上,来定义切入点。例如:你的一个类里,有15个方法,那就有至少十几个连接点了对吧,但是你并不想在所有方法附近都使用通知(使用叫织入,下面再说),你只是想让其中几个,在调用这几个方法之前、之后或者抛出异常时干点什么,那么就用切入点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法
注意:切入点定义的一般是你的业务中的某些方法(也有可能是某些特殊地方,在“特例”下有个例子切点切的就是方法,而是自定义的注解),就是供切面实际切入的地方,也就是需要执行通知的地方
- 切面
用来切插业务方法的类。
切面是通知和切入点的结合。现在发现了吧,没连接点什么事,链接点就是为了让你好理解切点搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的befor,after,around等就能知道),二切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义
- 目标
引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面,而自己专注于业务本身的逻辑。
- 代理
怎么实现整套AOP机制的,都是通过代理,这个一会儿给细说
- 织入(weaving)
把切面应用到目标对象来创建新的代理对象的过程。有三种方式,spring采用的是运行时,为什么是运行时,在上一文《Spring AOP开发漫谈之初探AOP及AspectJ的用法》中第二个标提到
- 目标对象
项目原始的Java组件。
- AOP代理
由AOP框架生成java对象。
- AOP代理方法
代理方法= advice + 目标对象的方法。
xml方式配置详解
- aop所需jar包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
- 在使用xml方式的Aop时,首先要保证xml头部引入了aop包和spring的基础包,如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
- 在spring-context.xml(也就是spring的主配置文件)中加入<aop:aspectj-autoproxy/>
- aop具体代码
<!-- 定义普通的Bean实例 -->
<bean id="adviceTest" class="com.abc.advice.AdviceTest" /> <aop:config> <!-- 将容器中的adviceTest转换成切面Bean --> <!-- 注意这里可以使用order属性为Aspect指定优先级 --> <aop:aspect id="firstAspect" ref="adviceTest" order="2"> <!-- @Before切点 --> <aop:before pointcut="execution(* com.abc.service.*.*(..))" method="permissionCheck" arg-names="name,age"/> <!-- @After切点 --> <aop:after pointcut="execution(* com.abc.service.*.*(..))" method="releaseResource"/> <!-- @AfterReturning切点 --> <aop:after-returning pointcut="execution(* com.abc.service.*.*(..))" method="log" returning="discussion" arg-names="discussion"/> <!-- @AfterThrowing切点 --> <aop:after-throwing pointcut="execution(* com.abc.service.*.*(..))" method="handleException"/> <!-- @Around切点(多个切点提示符使用and、or或者not连接) --> <aop:around pointcut="execution(* com.abc.service.*.*(..)) and args(name,time,..)" method="process"/><!-切入点第二种写法开始->
<!-单参数传参->
<aop:pointcut id="thinking" expression="execution(* com.bird.springidol.Thinker.thinkOfSomething(String)) and args(thoughts)"/>
<aop:pointcut id="log4add" expression="execution(* com.tfedu.discuss.web.TeacherDiscussionController.delete(com.tfedu.discuss.abutment.TestAddLog)) and args(testAddLog)" />
<aop:after method="addLog" pointcut-ref="log4add" arg-names="testAddLog"/>
<!-切入点第二种写法结束->
<!-切点为注解时,也就是将切点切到注解上 开始->
</aop:aspect> </aop:config>- pointcut-ref:当pointcut单独写时,在通知标签里,要是用pointcut-ref属性来指向响应的切点Id
- method:一般对应的是切面中的通知方法
- arg-names:定义的是通知方法中的参数。一般通知方法中需要使用切点方法的参数时,这个属性最好加上(当然有时不写也可以传参),并且和expression表达式中的args()的小括号中的名称保持一直
- order:
Spring中的事务是通过aop来实现的,当我们自己写aop拦截的时候,会遇到跟spring的事务aop执行的先后顺序问题,比如说动态切换数据源的问题,如果事务在前,数据源切换在后,会导致数据源切换失效,所以就用到了Order(排序)这个关键字.我们可以通过在@AspectJ的方法中实现org.springframework.core.Ordered 这个接口来定义order的顺序,order 的值越小,说明越先被执行
特例(某注解为切点时)
一般我们认为切点的位置都是某个业务方法之前,之后或者前后都有,但是有些情况下我们也可以将切点切到某个方法的注解上,在解决某些问题时很方便,下面举例说明此种用法:
配置文件中内容
<bean id="abutmentAspect" class="com.tfedu.discuss.abutment.aop.LogAspect"></bean>
<aop:config>
<aop:aspect id="" ref="abutmentAspect">
<aop:pointcut id="addLog" expression="@annotation(com.tfedu.discuss.annotation.BehaviorLog)" />
<aop:after method="behaviorLog4Review" pointcut-ref="addLog"/>
</aop:aspect>
</aop:config>
注解类
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
@Documented
public @interface BehaviorLog {
OperTypeEnum value();//这里面定义的方法要在注解上用到,这里的方法名就是注解上的等号左边的值
String fiterName();
}
注意:里面的方法可以根据具体需要来定义
注解的使用
在业务方法上加上:@BehaviorLog(value = OperTypeEnum.REVIEW, fiterName = "historyDraftId")
通知方法代码
public void behaviorLog4Review(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
String fiterName = method.getAnnotation(BehaviorLog.class).fiterName();//这里获取的是注解中定义的各种方法的值,例如这里获取的注解上的fiterName等号后面的的值
Object[] args = joinPoint.getArgs();//这里获取的是方法里的参数不是注解上的值,这个切记
Long historyDraftId = getParam4Common(args, fiterName);
HistoryDraftEntity historyDraftEntity = historyDraftBaseService.get(historyDraftId);
if (Util.isEmpty(historyDraftEntity)) {
ExceptionUtil.bEx("批阅中添加行为日志记录是,历史稿对象不能为空", historyDraftEntity);
}
addLog(historyDraftId, LogTypeEnum.WRITING.key(), historyDraftEntity.getTitle(), fetchUser.getCurrentUserId(),
OperTypeEnum.REVIEW.key());
}
private Long getParam4Common(Object[] args, String fiterName) {
Optional<Object> obj = Arrays.stream(args).findFirst();
if (!obj.isPresent()) {
return PARAM_ID;
}
return ConvertUtil.obj2long(BeanUtil.get((obj.get()), fiterName));
}
Aop的基本介绍的更多相关文章
- Spring入门篇——第6章 Spring AOP的API介绍
第6章 Spring AOP的API介绍 主要介绍Spring AOP中常用的API. 6-1 Spring AOP API的Pointcut.advice概念及应用 映射方法是sa开头的所有方法 如 ...
- AOP的成员介绍
AOP(Aspect Oriented Programming)面向切面编程,AOP的作用不过多介绍,本文是主要是介绍AOP的成员,是我在复习的时候记录的一些笔记,方便以后查阅方便一些. JointP ...
- spring aop做什么介绍
1.AOP(Aspect Orient Programming),称为面向切面编程,它作为面向对象(OOP)的一种补充,用于处理系统中分布于各个模板的横切关注点,比如事务管理.日志.缓存等.AOP实现 ...
- spring AOP(切面) 表达式介绍
在 spring AOP(切面) 例子基础上对表达式进行介绍 1.添加接口删除方法 2.接口实现类 UserDaoServer 添加实现接口删除方法 3.测试类调用delUser方法 4. 输出结果截 ...
- [刘阳Java]_Spring AOP注解详细介绍_第8讲
这节内容非常关键,我们会比较详细地介绍Spring AOP注解的使用 1. 要使用Spring AOP注解,必须满足如下的事项 导入Aspectj的jar.Spring3.0-AOP.jar.aopa ...
- Spring基础只是—AOP的概念介绍
Spring容器包含两个重要的特性:面向切面编程(AOP)和控制反转(IOC).面向切面编程是面向对象(OOP)的一种补充,在面向对象编程的过程中编程针对的目标是一个个对象,而面向切面编程中编程针对的 ...
- Spring Aop重要概念介绍及应用实例结合分析
转自:http://bbs.csdn.net/topics/390811099 此前对于AOP的使用仅限于声明式事务,除此之外在实际开发中也没有遇到过与之相关的问题.最近项目中遇到了以下几点需求,仔细 ...
- spring---aop(7)---Spring AOP中expose-proxy介绍
写在前面 expose-proxy.为是否暴露当前代理对象为ThreadLocal模式. SpringAOP对于最外层的函数只拦截public方法,不拦截protected和private方法(后续讲 ...
- spring---aop(6)---Spring AOP中ProxyFactoryBean介绍
写在前面 这篇文章里面就要说说Spring自己的AOP,搞清楚哪种方式是Spring自己实现的AOP,哪种方式是Spring引入aspectj的AOP. 简单例子 Spring自己的AOP实现在于Pr ...
随机推荐
- 【Unity】讯飞语音识别SDK
1.进入讯飞官网,注册帐号,进入控制台,创建新应用UnityXunfeiDemo,平台选Android.在当前应用这点下载SDK,添加AI能力(添加新服务),选择语音听写,即可下载安卓SDK(下称讯飞 ...
- AI金融知识自学偏量化方向-前提1
前提: 统计学习(统计分析)和机器学习之间的区别 金融公司采用机器学习技术及招募相关人才要求 第一个问题: 机器学习和统计学都是数据科学的一部分.机器学习中的学习一词表示算法依赖于一些数据(被用作训 ...
- android开发(49) Android 下拉刷新的实现。使用 SwipeRefreshLayout 代替 pull-to-refesh
概述 谷歌官方推出了SwipeRefreshLayout 来实现下拉刷新的效果.对比以前我们常用的 pull-to-refesh ,这个方案显得更加的简单方便. 关联项目引用(管理依赖) 在你的 应用 ...
- java-信息安全(十七)-*.PFX(*.p12)&个人信息交换文件
原文地址 http://snowolf.iteye.com/blog/735294 与计费系统打交道,少不了用到加密/解密实现.为了安全起见,通过非对称加密交换对称加密密钥更是不可或缺.那么需要通过什 ...
- 详解 Redis 应用场景及应用实例
redis(二)高级用法 详解 Redis 应用场景及应用实例 Redis 它是什么?它用来做什么?它的优势与短板如何? 告诉你Redis是一个牛逼货
- Android DiskLruCache完全解析,硬盘缓存的最佳方案(转)
概述 记得在很早之前,我有写过一篇文章<Android高效加载大图.多图解决方案,有效避免程序OOM>,这篇文章是翻译自Android Doc的,其中防止多图OOM的核心解决思路就是使用L ...
- [Laravel] 02 - Route and MVC
前言 一.良心资料 英文 Laravel 框架:https://laravel.com/ 教程:https://laracasts.com/series/ laravel-from-scratch-2 ...
- 【Docker】退出容器和进入容器
运行容器:docker run -it 镜像名 /bin/bash 退出容器: exit 或者 Ctrl+P+Q 查看容器:docker ps -a 查看运行的容器:docker ps 重启容器:do ...
- NLP入门资料
<统计自然语言处理> 一些基础理论概念,涉及统计自然语言处理的基本概念.理论方法和新研究进展,内容包括形式语言与自动机及其在自然语言处理中的应用.语言模型.隐马尔可夫模型.语料库技术.汉语 ...
- mui+回复弹出软键盘
最近再做一个APP的时候,有一个评论回复的功能,在做APP的时候,直接用手指触发focus事件,来唤醒软键盘的弹出没有问题, 但是现在的功能需要对点击回复进行弹出软键盘来操作,参考过很多都有问题,后来 ...