@AspectJ切点函数详解

相关文章链接:

Spring AOP原理详解及实例

观前提示:

本文所使用的IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141,Tomcat版本为9.0.12。

类别 函数 入参 说明
方法切点函数 execution() 方法匹配模式串 满足某一匹配模式的所有目标类方法连接点
方法切点函数 @annotation() 方法注解类名 标注了特定注解的目标方法连接点
方法入参切点函数 args() 类名 定位于入参为特定类型的方法的连接点
方法入参切点函数 @args() 类型注解类名 定位于被特定注解所标注入参的方法的连接点
目标类切点函数 within() 类名匹配串 定位于特定作用域下的所有连接点
目标类切点函数 target() 类名 定位于指定类及其子类
目标类切点函数 @within() 类型注解类名 定位与标注了特定注解的类及其实现类
目标类切点函数 @target() 类型注解类名 定位于标注了特定注解的目标类里所有方法
代理类切点函数 this() 类名 代理类按类型匹配与指定类,则被代理的目标类的所有连接点都匹配与该切点

1 方法切点函数

1.1 execution()

语法表达式如下:

execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)

其中:返回类型模式、方法名模式、参数模式是必选项

1.1.1 通过方法签名定义切点

execution(public * *(..)) 

匹配所有目标类的public方法。第一个 * 代表任意返回类型,第二个 * 代表方法名,而 . . 代表任意入参的方法。

execution(public String *(..))

匹配所有目标类修饰符为public,返回参数类型为String的方法。第一个 * 代表方法名,而 . . 代表任意入参的方法。

1.1.2 通过类定义切点

execution(* com.example.UserService.*(..))

匹配com.example.UserService接口中所有方法。第一个 * 代表任意返回类型,第二个 * 代表com.example.UserService中的所有方法,. . 代表任意入参的方法。

1.1.3 通过类包定义切点

execution(* com.example.*(..))

匹配com.example包下的所有方法。

execution(* com..*(..))

匹配com包及子孙包下所有方法。

类名模式 说明
.* 包中所有的类,不包括子孙包下的类
. .* 包及子孙包下所有的类

1.1.4 通过方法入参定义切点

execution(* com.example.UserService.insert(String,int))

匹配com.example.UserService包下的insert(String,int)方法。

execution(* com.example.UserService.insert(String, *))

匹配com.example.UserService包下的insert()方法,其中第一个参数类型为String,第二个参数类型为任意参数类型。

execution(* com.example.UserService.insert(String,..))

匹配com.example.UserService包下的insert()方法,其中第一个参数类型为String,后面的参数类型为任意类型且个数不限。

execution(* com.example.UserService.insert(Object+))

匹配com.example.UserService包下的insert()方法,方法只有一个入参,为Object类型或Object类型的子类。

类名模式 说明
* 表示任意类型的参数
. . 表示任意个数任意类型的参数

1.1.5 例子

这里给出的例子为通过类定义切点,其他定义切点方式可修改LogAop.java中的注解@Pointcut("execution(* testAop.UserService.*(..))")即可

目录结构
在这里插入图片描述
applicationContext.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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <bean id="userService" class="testExecution.UserService"/>
    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="testExecution"></context:component-scan>
    <!-- 开启aop注解方式,此步骤不能少,这样java类中的aop注解才会生效 -->
    <aop:aspectj-autoproxy/>
</beans>

UserService.java

package testExecution;

public class UserService {
   

    public void insertUser() {
   
        System.out.println("插入用户成功");
    }

    public boolean updateUser() {
   
        System.out.println("更新用户成功");
        return true;
    }
}

LogAop.java

package testExecution;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class LogAop {
   

    @Pointcut("execution(* testExecution.UserService.*(..))")
    public void ponitCut() {
   

    }

    @Before("ponitCut()")
    public void beforeAdvice() {
   
        System.out.println("beforeAdvice");
    }

    @After("ponitCut()")
    public void afterAdvice() {
   
        System.out.println("afterAdvice");
    }

    //环绕通知。注意要有ProceedingJoinPoint参数传入
    @Around("ponitCut()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
   
        System.out.println("注解类型环绕通知..环绕前");
        pjp.proceed();//执行方法
        System.out.println("注解类型环绕通知..环绕后");
    }
}

TestAop.java

package testExecution;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {
   

    private ClassPathXmlApplicationContext ac;

    @Before
    public void before() {
   
        ac = new ClassPathXmlApplicationContext("testExecution/applicationContext.xml");
    }

    @Test
    public void test() {
   
        try {
   
            UserService userService = (UserService) ac.getBean("userService");
            userService.insertUser();
        } catch (Exception e) {
   
            e.printStackTrace();
        }
    }
}

运行结果

在这里插入图片描述

1.2 @annotation()

用于标注了某个注解的目标切点。

1.2.1 例子

目录结构如下:
在这里插入图片描述

自定义注解 SystemLog.java

package testAnnotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME) //注解保留期限
@Target(ElementType.METHOD) //注解目标类型
@Documented
public @interface SystemLog {
   
    int LogType() default Constants.LogType.Empty;
}

注:@Rentention,@Target,@Document注解描述可参考文章:java元注解

常量类Constants.java

package testAnnotation;

public class Constants {
   

    public static class LogType {
   
        public static final int Empty = 0;//默认为0
        public static final int Insert = 1;//插入操作日志
        public static final int Update = 2;//更新操作日志
    }
}

applicationContext.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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <bean id="userService" class="testAnnotation.UserService"/>
    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="testAnnotation"></context:component-scan>
    <!-- 开启aop注解方式,此步骤不能少,这样java类中的aop注解才会生效 -->
    <aop:aspectj-autoproxy/>
</beans>

UserService.java

package testAnnotation;

public class UserService {
   

    @SystemLog
    public void defaultMethod(String param){
   
        System.out.println("默认方法,入参为:" + param);
    }

    @SystemLog(LogType = Constants.LogType.Insert)
    public void insertUser() {
   
        System.out.println("插入用户成功");
    }

    @SystemLog(LogType = Constants.LogType.Update)
    public boolean updateUser() {
   
        System.out.println("更新用户成功");
        return true;
    }
}

LogAop.java

package testAnnotation;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org
  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我会根据您的要求回答您的问题。 首先,@After是Spring AOP中的一种通知类型,用于在目标方法执行后执行一些操作。要实现@After通知,我们需要创建一个类,并在该类中编写一个带有@After注释的方法。该方法应该接受一个JoinPoint类型的参数,以便我们可以获得目标方法的信息。 其次,为了对使用了@MyLogAnnotation标注的方法进行前置增强,我们需要定义一个@Pointcut切点,来匹配所有使用了@MyLogAnnotation标注的方法。 下面是一个示例: ```java import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyLogAspect { @Pointcut("@annotation(com.example.MyLogAnnotation)") public void myLogAnnotationPointcut() {} @After("myLogAnnotationPointcut()") public void logAfter(JoinPoint joinPoint) { // 在这里记录日志或执行其他操作 System.out.println("Method executed: " + joinPoint.getSignature().getName()); } } ``` 在上面的代码中,我们定义了一个名为MyLogAspect的类,并使用@Aspect注释将其标记为切面。然后,我们定义了一个名为myLogAnnotationPointcut的@Pointcut切点,用于匹配所有使用了@MyLogAnnotation标注的方法。最后,我们定义了一个名为logAfter的方法,并使用@After注释将其标记为@MyLogAnnotation标注方法的后置通知。此方法使用JoinPoint参数获取目标方法的信息,并在控制台上记录方法已执行的消息。 为了验证这个通知是否正常工作,我们可以创建一个简单的Spring应用程序,并在ApplicationContext中注册MyLogAspect类。然后,我们可以在一个类的方法上使用@MyLogAnnotation标注,并观察是否记录了日志。 以下是一个示例应用程序的代码: ```java import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); MyService service = context.getBean("myService", MyService.class); service.doSomething(); } } ``` 在上面的代码中,我们创建了一个名为MyService的类,其中包含一个使用@MyLogAnnotation标注的方法。然后,我们在Spring ApplicationContext中注册了MyLogAspect类,并从中获取了MyService的实例。最后,我们调用了MyService的doSomething方法。 如果一切正常,我们应该会在控制台上看到以下输出: ``` Method executed: doSomething ``` 这表明我们的切面已经拦截了使用了@MyLogAnnotation标注的方法,并执行了我们定义的操作。 希望这个示例可以帮助您理解如何实现@After注解并对使用了@MyLogAnnotation标注的方法进行前置增强,并在Spring应用程序中使用它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值