Aspect Oriented Programing 面向切面编程,相比拟 oop 面向对象编程来说,Aop 关注的不再是程序代码中某个类,某些办法,而 aop 思考的更多的是一种面到面的切入,即层与层之间的一种切入,所以称之为切面。联想大家吃的汉堡(两头夹肉)。那么 aop 是怎么做到拦挡整个面的性能呢?思考学到的 servlet urlpattern /* 的配置,实际上也是 aop 的实现 。
Spring Aop 实现的形式
- 注解 形式
- XML 形式
案例实操
注解形式
jar 包坐标引入
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version></dependency>
beans.xml 配置
增加命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
配置 Aop 代理
<aop:aspectj-autoproxy/>
编写 aop 实现类
/*** 申明切面组件*/@Component@Aspectpublic class LogCut { /** * 定义切入点 匹配办法规定定义 * 匹配规定表达式含意 拦挡 com.xxx.service 包下 以及子包下 所有类的所有办法 */ @Pointcut("execution (* com.xxx.service..*.*(..))") public void cut(){} /** * 申明前置告诉 并将告诉利用到定义的切入点上 * 指标类办法执行前 执行该告诉 */ @Before(value="cut()") public void before(){ System.out.println("前置告诉....."); } /** * 申明返回告诉 并将告诉利用到切入点上 * 指标类办法执行结束执行该告诉 */ @AfterReturning(value="cut()") public void afterReturning(){ System.out.println("返回告诉...."); } /** * 申明最终告诉 并将告诉利用到切入点上 * 指标类办法执行过程中是否产生异样 均会执行该告诉 相当于异样中的 finally */ @After(value="cut()") public void after(){ System.out.println("最终告诉...."); } /** * 申明异样告诉 并将告诉利用到切入点上 * 指标类办法执行时产生异样 执行该告诉 */ @AfterThrowing(value="cut()",throwing="e") public void afterThrowing(Exception e){ System.out.println("异样告诉....办法执行异样时执行:"+e); } /** * 申明盘绕告诉 并将告诉利用到切入点上 * 办法执行前后 通过盘绕告诉定义相应解决 */ @Around(value="cut()") public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("盘绕前置..."); System.out.println("盘绕告诉"); System.out.println(pjp.getTarget()+"--"+pjp.getSignature()); Object result=pjp.proceed();//执行指标对象办法 System.out.println("盘绕后置..."); return result; } }
Aop 匹配办法规定表达式语言(简要理解)
Aop 切入点表达式简介
执行任意公共办法:
execution(public *(..))
执行任意的 set 办法
execution(* set*(..))
执行 com.xxx.service 包下任意类的任意办法
execution(* com.xxx.service.*.*(..))
执行 com.xxx.service 包 以及子包下任意类的任意办法
execution(* com.xxx.service..*.*(..))
xml 形式
配置切面、切入点、告诉
<!-- aop 相干配置 --><aop:config> <!-- aop 切面配置 --> <aop:aspect ref="logCut"> <!-- 定义 aop 切入点 --> <aop:pointcut expression="execution (* com.xxx.service..*.*(..))" id="cut"/> <!-- 配置前置告诉 指定前置告诉办法名 并援用切入点定义 --> <aop:before method="before" pointcut-ref="cut"/> <!-- 配置返回告诉 指定返回告诉办法名 并援用切入点定义 --> <aop:after-returning method="afterReturning" pointcut-ref="cut"/> <!-- 配置异样告诉 指定异样告诉办法名 并援用切入点定义 --> <aop:after-throwing method="afterThrowing" throwing="e" pointcut-ref="cut"/> <!-- 配置最终告诉 指定最终告诉办法名 并援用切入点定义 --> <aop:after method="after" pointcut-ref="cut"/> <!-- 配置盘绕告诉 指定盘绕告诉办法名 并援用切入点定义 --> <aop:around method="around" pointcut-ref="cut"/> </aop:aspect></aop:config>
定义 bean
/*** 申明切面组件*/@Componentpublic class LogCut { public void before(){ System.out.println("前置告诉....."); } public void afterReturning(){ System.out.println("返回告诉...."); } public void after(){ System.out.println("最终告诉...."); } public void afterThrowing(Exception e){ System.out.println("异样告诉....办法执行异样时执行:" + e); } public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("盘绕前置..."); System.out.println("盘绕告诉"); System.out.println(pjp.getTarget()+"--"+pjp.getSignature()); Object result=pjp.proceed(); System.out.println("盘绕后置..."); return result; }}
扩大
AOP 的基本概念
JoinPoint(连接点)【动静】
被拦挡到的每个点,spring 中指被拦挡到的每一个办法,spring aop 一个连接点即代表一个办法的执行。
Pointcut(切入点)【动态】
对连接点进行拦挡的定义(匹配规定定义 规定拦挡哪些办法,对哪些办法进行解决),spring 这块有专门的表达式语言定义。
Advice(告诉){重点}
拦挡到每一个连接点即(每一个办法)前后所要做的操作
- 前置告诉(前置加强)--before() 执行办法前告诉
- 返回告诉(返回加强)--afterReturning 办法失常完结返回后的告诉
- 异样抛出告诉(异样抛出加强)--afetrThrow()
- 最终告诉 --after 无论办法是否产生异样,均会执行该告诉
- 盘绕告诉 --around 突围一个连接点(join point)的告诉,如办法调用。这是最弱小的一种告诉类型。 盘绕告诉能够在办法调用前后实现自定义的行为。它也会抉择是否继续执行连接点或间接返回它们本人的返回值或抛出异样来完结执行
Aspect(切面)
切入点与告诉的联合,决定了切面的定义,切入点定义了要拦挡哪些类的 哪些办法,告诉则定义了拦挡办法后要做什么,切面则是横切关注点的形象,与类类似,类是对物体特色的形象,切面则是横切关注点形象。
Target(指标对象)
被代理的指标对象
Weave(织入)
将切面利用到指标对象并生成代理对象的这个过程即为织入(过程)。
Introduction(引入)
在不批改原有利用程序代码的状况下,在程序运行期为类动静增加办法或者字段的过程称为引入。