@AspectJ可以使用切点函数定义切点,我们还可以使用逻辑运算符对切点进行复核运算得到复合的切点,为了在切面中重用切点,我们还可以对切点进行命名,以便在其他的地方引用定义过的切点。当一个连接点匹配多个切点时,需要考虑织入顺序的问题,此外一个重要的问题是如何再增强中访问连接点上下文的信息。

Waiter接口:

package com.yyq.aspectJAdvanced;
public interface Waiter {
void greetTo(String name);
void serveTo(String name);
}

NaiveWaiter实现类:

package com.yyq.aspectJAdvanced;
public class NaiveWaiter implements Waiter {
@Override
public void greetTo(String name) {
System.out.println("NaiveWaiter:greet to " + name + "...");
}
@Override
public void serveTo(String name) {
System.out.println("NaiveWaiter:serving to " + name + "...");
}
public void smile(String clientName,int times){
System.out.println("NaiveWaiter:smile to "+clientName+ times+"times...");
}
}

 NaughtyWaiter实现类:

package com.yyq.aspectJAdvanced;
public class NaughtyWaiter implements Waiter {
public void greetTo(String clientName) {
System.out.println("NaughtyWaiter:greet to " + clientName + "...");
}
public void serveTo(String clientName) {
System.out.println("NaughtyWaiter:serving " + clientName + "...");
}
public void joke(String clientName, int times) {
System.out.println("NaughtyWaiter:play " + times + " jokes to " + clientName + "...");
}
}

Seller接口:

package com.yyq.aspectJAdvanced;
public interface Seller {
int sell(String goods, String clientName);
}

SmallSeller实现类:

package com.yyq.aspectJAdvanced;
public class SmartSeller implements Seller {
public int sell(String goods,String clientName) {
System.out.println("SmartSeller: sell "+goods +" to "+clientName+"...");
return 100;
} public void checkBill(int billId){
if(billId == 1) throw new IllegalArgumentException("iae Exception");
else throw new RuntimeException("re Exception");
}
}

beans.xml配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="naiveWaiter" class="com.yyq.aspectJAdvanced.NaiveWaiter"/>
<bean id="naughtyWaiter" class="com.yyq.aspectJAdvanced.NaughtyWaiter"/>
<bean id="seller" class="com.yyq.aspectJAdvanced.SmartSeller"/>
<!--
<bean class="com.yyq.aspectJAdvanced.TestAspect"/> <bean class="com.yyq.aspectJAdvanced.TestAspect2"/>
<bean class="com.yyq.aspectJAdvanced.TestAspect3"/>
<bean class="com.yyq.aspectJAdvanced.TestAspect4"/>
<bean class="com.yyq.aspectJAdvanced.TestAspect5"/>
<bean id="naiveWaiter2" class="com.yyq.aspectJAdvanced.NaiveWaiter2"/>
<bean class="com.yyq.aspectJAdvanced.TestAspect6"/>
<bean class="com.yyq.aspectJAdvanced.TestAspect7"/>
<bean class="com.yyq.aspectJAdvanced.TestAspect8"/>
-->
</beans>
1、切点符合运算
    使用切点符合运算符,我们将拥有强大而灵活的切点表达能力。
TestAspect:切点符合运算定义切面

package com.yyq.aspectJAdvanced;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; @Aspect
public class TestAspect {
//与非运算
@Before("!target(com.yyq.aspectJAdvanced.NaiveWaiter) && execution(* serveTo(..))")
public void notServeInNaiveWaiter(){
System.out.println("--notServeInNaiveWaiter() executed!--");
}
//与运算
@After("within(com.yyq.aspectJAdvanced.*) && execution(* greetTo(..))")
public void greetToFun(){
System.out.println("--greetToFun() executed!--");
}
//或运算
@AfterReturning("target(com.yyq.aspectJAdvanced.Waiter) || target(com.yyq.aspectJAdvanced.Seller)")
public void waiterOrSeller(){
System.out.println("--waiterOrSeller() executed!--");
}
}

测试方法:

 @Test
public void pointAspectJTest() {
String configPath = "com\\yyq\\aspectJAdvanced\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter naiveWaiter = (Waiter) ctx.getBean("naiveWaiter");
Waiter naughtyWaiter = (Waiter) ctx.getBean("naughtyWaiter");
naiveWaiter.greetTo("John");
naiveWaiter.serveTo("John");
naughtyWaiter.greetTo("Tom");
naughtyWaiter.serveTo("Tom");
}
输出结果:
NaiveWaiter:greet to John...
--greetToFun() executed!--
--waiterOrSeller() executed!--
NaiveWaiter:serving to John...
--waiterOrSeller() executed!--
NaughtyWaiter:greet to Tom...
--greetToFun() executed!--
--waiterOrSeller() executed!--
--notServeInNaiveWaiter() executed!--
NaughtyWaiter:serving Tom...
--waiterOrSeller() executed!--
 
2、命名切点
    切点直接声明在增强方法处被称为匿名切点,匿名切点只能在声明处使用。如果希望在其他地方重用一个切点,我们可以通过@Pointcut注解以及切面类方法对切点进行命名。
TestNamePointcut:命名切点类

package com.yyq.aspectJAdvanced;
import org.aspectj.lang.annotation.Pointcut;
public class TestNamePointcut {
//通过注解方法inPackage()对该切点进行命名,方法可视域修饰符为private,表明该命名切点只能在本切面类中使用
@Pointcut("within(com.yyq.aspectJAdvaned.*)")
private void inPackage(){}
@Pointcut("execution(* greetTo(..))")
protected void greetTo(){}
@Pointcut("inPackage() and greetTo()")
public void inPkgGreetTo(){}
}

TestAspect2:切面实现类

package com.yyq.aspectJAdvanced;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class TestAspect2 {
@Before("TestNamePointcut.inPkgGreetTo()")
public void pkgGreetTo(){
System.out.println("--pkgGreetTo() executed!--");
}
@Before("target(com.yyq.aspectJAdvanced.NaiveWaiter) || TestNamePointcut.inPkgGreetTo()")
public void pkgGreetToNotnaiveWaiter(){
System.out.println("--pkgGreetToNotnaiveWaiter() executed!--");
}
}

测试方法:

@Test
public void pointAspectJTest2() {
String configPath = "com\\yyq\\aspectJAdvanced\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
NaiveWaiter naiveWaiter = (NaiveWaiter) ctx.getBean("naiveWaiter");
naiveWaiter.smile("Andy", 2);
}
输出结果:
--pkgGreetToNotnaiveWaiter() executed!--
NaiveWaiter:smile to  Andy2times...
 
3、增强织入的顺序
    一个连接点可以同时匹配多个切点,切点对应的增强在连接点上的织入顺序的安排主要有以下3种情况:
    1)如果增强在同一个切面类中声明,则依照增强在切面类中定义的顺序进行织入;
    2)如何增强位于不同的切面类中,且这些切面类都实现了org.springframework.core.Order接口,则由接口方法的顺序号决定(顺序号小的先织入);
    3)如果增强位于不同的切面类中,且这些切面类没有实现org.springframework.core.Order接口,织入的顺序是不确定的。
 
4、访问连接点信息
    AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口,任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。
TestAspect3:切面实现类

@Aspect
public class TestAspect3 {
@Around("execution(* greetTo(..)) && target(com.yyq.aspectJAdvanced.NaiveWaiter)")
public void joinPointAccess(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("---joinPointAccess---");
System.out.println("args[0]:" + pjp.getArgs()[0]);
System.out.println("signature:" + pjp.getTarget().getClass());
pjp.proceed();
System.out.println("---joinPointAccess---");
}
}

测试方法:

 @Test
public void pointAspectJTest3() {
String configPath = "com\\yyq\\aspectJAdvanced\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter naiveWaiter = (Waiter) ctx.getBean("naiveWaiter");
naiveWaiter.greetTo("Andy");
}
输出结果:
---joinPointAccess---
args[0]:Andy
signature:class com.yyq.aspectJAdvanced.NaiveWaiter
NaiveWaiter:greet to Andy...
---joinPointAccess---
 
5、绑定连接点方法入参
    args()用于绑定连接点方法的入参;@annotation()用于绑定连接点方法的注解对象;而@args()用于绑定连接点方法入参的注解。
TestAspect4:切面实现类

@Aspect
public class TestAspect4 {
@Before("target(com.yyq.aspectJAdvanced.NaiveWaiter) && args(name,num,..)")
public void bindJoinPointParams(int num, String name) {
System.out.println("---bindJoinPointParams---");
System.out.println("name:" + name);
System.out.println("num:" + num);
System.out.println("---bindJoinPointParams---");
}
}

测试方法:

@Test
public void pointAspectJTest4() {
String configPath = "com\\yyq\\aspectJAdvanced\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
NaiveWaiter naiveWaiter = (NaiveWaiter) ctx.getBean("naiveWaiter");
naiveWaiter.smile("Andy", 3);
}
输出结果:
---bindJoinPointParams---
name:Andy
num:3
---bindJoinPointParams---
NaiveWaiter:smile to  Andy 3 times...
 
6、绑定代理对象
    使用this()或target()可绑定被代理对象实例,在通过类实例名绑定对象时,还依然具有原来连接点匹配的功能,只不过类名是通过增强方法中同名入参的类型间接决定罢了。
TestAspect5:切面实现类

@Aspect
public class TestAspect5 {
@Before("this(waiter)")
public void bindProxyObj(Waiter waiter){
System.out.println("---bindProxyObj---");
System.out.println(waiter.getClass().getName());
System.out.println("---bindProxyObj---");
}
}

测试方法:

@Test
public void pointAspectJTest5() {
String configPath = "com\\yyq\\aspectJAdvanced\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter) ctx.getBean("naiveWaiter");
waiter.greetTo("Yang");
}
输出结果:
---bindProxyObj---
com.yyq.aspectJAdvanced.NaiveWaiter$$EnhancerByCGLIB$$fefafe52
---bindProxyObj---
NaiveWaiter:greet to Yang...
 
7、绑定类注解对象
    @within()和@target()函数可以将目标类的注解对象绑定到增强方法中,我们通过@within()演示注解绑定的操作。
TestAspect6:切面测试类

@Aspect
public class TestAspect6 {
@Before("@within(m)")
public void bindTypeAnnoObject(Monitorable m) {
System.out.println("---bindTypeAnnoObject---");
System.out.println(m.getClass().getName());
System.out.println("---bindTypeAnnoObject---");
}
}

测试方法:

@Test
public void pointAspectJTest6() {
String configPath = "com\\yyq\\aspectJAdvanced\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter) ctx.getBean("naiveWaiter2");
((NaiveWaiter2)waiter).greetTo("Yang");
}
输出结果:
---bindTypeAnnoObject---
$Proxy4
---bindTypeAnnoObject---
NaiveWaiter:greet to Yang...
 
8、绑定返回值
    在后置增强中,我们可以通过returning绑定连接点方法的返回值。
TestAspect7:切面实现类

@Aspect
public class TestAspect7 {
@AfterReturning(value = "target(com.yyq.aspectJAdvanced.SmartSeller)", returning = "retVal")
public void bindReturnValue(int retVal) {
System.out.println("---bindReturnValue---");
System.out.println("returnValue:" + retVal);
System.out.println("---bindReturnValue---");
}
}

测试方法:

 @Test
public void pointAspectJTest7() {
String configPath = "com\\yyq\\aspectJAdvanced\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
SmartSeller seller = (SmartSeller) ctx.getBean("seller");
seller.sell("Beer", "John");
}
输出结果:
SmartSeller: sell Beer to John...
---bindReturnValue---
returnValue:100
---bindReturnValue---
 
9、绑定抛出的异常
    和通过切点函数绑定连接点信息不同,连接点抛出的异常必须使用AfterThrowing注解的throwing成员进行绑定。
TestAspect8:切面实现类

@Aspect
public class TestAspect8 {
@AfterThrowing(value = "target(com.yyq.aspectJAdvanced.SmartSeller)", throwing = "iae")
public void bindException(IllegalArgumentException iae) {
System.out.println("---bindException---");
System.out.println("exception:" + iae.getMessage());
System.out.println("---bindException---");
}
}

测试方法:

 @Test
public void pointAspectJTest8() {
String configPath = "com\\yyq\\aspectJAdvanced\\beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
SmartSeller seller = (SmartSeller) ctx.getBean("seller");
seller.checkBill(1);
}
输出结果:
---bindException---
exception:iae Exception
---bindException---
 
java.lang.IllegalArgumentException: iae Exception
 
 
 
 
 

Spring AOP @AspectJ进阶的更多相关文章

  1. Spring AOP + AspectJ annotation example

    In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...

  2. Spring AOP + AspectJ Annotation Example---reference

    In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...

  3. 关于 Spring AOP (AspectJ) 该知晓的一切

    关联文章: 关于Spring IOC (DI-依赖注入)你需要知道的一切 关于 Spring AOP (AspectJ) 你该知晓的一切 本篇是年后第一篇博文,由于博主用了不少时间在构思这篇博文,加上 ...

  4. Spring学习(十八)----- Spring AOP+AspectJ注解实例

    我们将向你展示如何将AspectJ注解集成到Spring AOP框架.在这个Spring AOP+ AspectJ 示例中,让您轻松实现拦截方法. 常见AspectJ的注解: @Before – 方法 ...

  5. 关于 Spring AOP (AspectJ) 你该知晓的一切

    版权声明:本文为CSDN博主「zejian_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/javazej ...

  6. 关于 Spring AOP (AspectJ) 你该知晓的一切 (转)

    出处:关于 Spring AOP (AspectJ) 你该知晓的一切

  7. Spring AOP AspectJ Pointcut Expressions With Examples--转

    原文地址:http://howtodoinjava.com/spring/spring-aop/writing-spring-aop-aspectj-pointcut-expressions-with ...

  8. Spring AOP AspectJ

    本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代码. Pointcut:注入Advice的位置,切入点,一般为某 ...

  9. spring AOP AspectJ 定义切面实现拦截

    总结记录一下AOP常用的应用场景及使用方式,如有错误,请留言. 1.  讲AOP之前,先来总结web项目的几种拦截方式    A:  过滤器 使用过滤器可以过滤URL请求,以及请求和响应的信息,但是过 ...

随机推荐

  1. 编写支持SSR的通用组件指南

    原文来自:https://blog.lichter.io/posts/the-guide-to-write-universal-ssr-ready-vue-compon? utmcampaign=Vu ...

  2. jquery的deferred使用详解

    原文:hhtps://www.cnblogs.com/shijingjing07/p/6403450.html -------------------------------------------- ...

  3. jsp执行过程图解

    转自:https://blog.csdn.net/y277an/article/details/76561451 一.jsp执行过程图解 用户访问jsp页面时,jsp的处理过程如下图所示: 二.预处理 ...

  4. 人人网框架导入uidGenerator的ID生成方式

    人人网框架导入uidGenerator的ID生成方式 2019-03-11 LIUREN    SpringBoot2.0  uidGenerator  SpringBoot2.0  uidGener ...

  5. Java 基础【19】代理

    Java 代理(Proxy)模式与现实中的代理含义一致,如旅游代理.明星的经纪人. 在目标对象实现基础上,增加额外的功能操作,由此来扩展目标对象的功能. JavaWeb 中最常见的过滤器.Struts ...

  6. 怎么样加快JavaScript加载和执行效率

    概览 无论当前 JavaScript 代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成.JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长.浏览器在下载 ...

  7. [转]ThreadLocal使用

    引言 ThreadLocal的官方API解释为: “该类提供了线程局部 (thread-local) 变量.这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线 ...

  8. python3 利用正则获取网页中的想保存下来的内容

    需要获取某个网页中表格部分中某个产品的成份 分析在html中成份的元素代码 <a href="/composition/4c3060178d1184935a48c4e51be4f63f ...

  9. Spring Boot系列——日志配置

    日志,通常不会在需求阶段作为一个功能单独提出来,也不会在产品方案中看到它的细节.但是,这丝毫不影响它在任何一个系统中的重要的地位. 为了保证服务的高可用,发现问题一定要即使,解决问题一定要迅速,所以生 ...

  10. 【转】jQuery 的 ajax 方法,返回结果 readyState=4 并且 status=200 时,还进 error 方法

    今天在使用jquery.ajax方法去调用后台方法时,ajax中得参数data类型是"JSON",后台DEBUG调试,运行正常,返回正常的结果集,但是前端一直都进到ajax的err ...