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 ...
随机推荐
- Android 自动化测试——Monkey测试
Android自带了很多方便的测试工具和方法,包括我们常用的单元测试.Robotium测试.Monkey测试.MonkeyRunner测试.senevent模拟等.这些方法对于我们编写高质量的APP十 ...
- 【iCore4 双核心板】4.3寸液晶模块程序发布
一.说明 1.本资料包程序包含两部分,"CAPTURE"为液晶显示截图,"tft4.3"为ARM程序. 2.此程序只适合iCore4液晶模块. 3.iCore4 ...
- Java知多少(53)使用Java创建自己的异常子类
尽管Java的内置异常处理大多数常见错误,你也许希望建立你自己的异常类型来处理你所应用的特殊情况.这是非常简单的:只要定义Exception的一个子类就可以了(Exception当然是Throwabl ...
- 分布式系统CAP理论与CA选择
总结: CAP指的是数据一致性.服务可用性.分区容错性:(这里的一致性指的是强一致性,又叫原子性或线性一致性:可用性指的是所有读写操作都要能终止,没有时延上的要求) 分布式系统中P是必选项:在P必选的 ...
- Best Practices in Asynchronous Programming
http://blog.stephencleary.com/ http://blogs.msdn.com/b/pfxteam/
- 分发系统介绍 expect脚本远程登录 expect脚本远程执行命令 expect脚本传递参数
expect脚本远程登录 yum install -y expect yum install -y tcl tclx tcl-devel 自动远程登录 #! /usr/bin/expect set h ...
- react-router 4.3 js实现跳转
import React, {Component} from 'react'; import { NavLink,Link } from "react-router-dom"; i ...
- [Ubuntu] LightDM 轻量级桌面显示管理器
LightDM(Light Display Manager)是一个全新的轻量级 Linux 桌面显示管理器,而传统的 Ubuntu 是使用 GNOME 桌面标准的 GDM. LightDM 是一个跨桌 ...
- ios 消除 字符串 首尾空格
本文转载至 http://blog.csdn.net/reylen/article/details/8233353 (1)系统去首尾空格方法,使用NSString中的str = [str string ...
- 四、K3 Cloud 开发插件《K3 Cloud事件、方法、函数》
1.简单帐表/动态表单几个主要事件 //初始化 public override void Initialize() //构建动态列 public override BOS.Core.Report.Re ...