AspectJ的切入表达式

1. AspectJ定义了专门的表达式用于切入点,表达式的原型是

execution(modifiers-pattern? ret-type-pattern
		declaring-type-pattern?name-pattern(param-pattern)
		throws-pattern?)
  1. modifiers-pattern 访问权限类型(public,protected,private,默认)
  2. ret-type-pattern 返回值类型 (void,简单类型,引用类型等)
  3. declaring-type-pattern 包名类型
  4. name-pattern(param-pattern) 方法名(参数类型和参数个数)
  5. throws-pattern 抛出异常类型
  6. ? 表示可选的部分

以上表达式共四个部分.
execution(访问权限 方法返回值 方法声明(参数) 异常类型)

切入点表达式要匹配的对象就是目标方法的方法名,所以,execution表达式
中明显就是方法的签名,注意,表达式中不是粗体的部分表示可省略部分
各部分间用空格分开,其中可以使用以下符号

符号意义
*0至多个任意字符
.. 用在方法参数中,表示任意多个参数
用在方法参数中,表示任意多个参数
*用在类名后,表示当前类及其子类
用在接口后面,表示当前接口及其实现类

举例说明

//指定切入点为任意公共方法
execution(public * *(..))
//指定切入点为任意"set"开头的方法
ececution(* set*(..))
//指定切入点:service包中的任意类的任意方法
execution(* com.ezj.service.*.*(..))
//指定切入点:定义在service包或者其子包中的任意类中的任意方法
//".."出现在类名中时,后面必须跟"*",表示包,子包下的所有类
execution(* com.wzj.service..*.*(..))
//指定切入点:表示所有包在的service子包中的所有类中的所有方法
execution(* *..service.*.*(..))

2.目标对象和代理对象

目标对象:在SpringAOP被增强的对象

代理对象:通过aop中对目标对象进行增强,加入代理逻辑的而产生的对象

3.AspectJ在项目中的使用

@Aspect: 是aspect框架中的注解
作用:表示当前类是切面类
切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
位置:在类的定义上面

@Aspect
 
public class MyAspect {
}

使用AspectJ的时候,要在配种文件中加入

    <!-- 声明自动代理生成器:使用aspect框架内部的功能,创建目标对象的代理对象
        创建代理对象是在内存中实现的,修改目标对象的内存中的结构,创建为代理对象
        所以目标对象就是被修改后的代理对象

        aspectj-autoproxy:会把spring容器中的所有目标对象,一次性都生成代理对象
    -->
    <aop:aspectj-autoproxy/>

4.在AspectJ中击中常用注解的使用

1.@Before

  • @Before() 前置注解通知
    属性 value 是切入表达式,表示切入的功能执行的位置
    位置 : 在方法的上面
    特点:
    1.在目标方法之前执行
    2.不会改变目标方法的执行结构
    3.不会影响目标方法的执行
/**前置通知方法方法,方法是实现切面功能的
方法的定义要求:
1.公共方法 public
2.方法没有返回值
3.方法名称自定义
4.方法可以有参数,也可以没有参数
     如果有参数,参数不是自定义的*/
@Before(value = "execution(* *..doSome(String,Integer))")
    public void MyBefore(JoinPoint jp){
     //就是切面要执行的功能代码
        System.out.println("1前置通知,切面功能:在目标方法之前输出执行时间:"+new Date());
    }

2.JoinPoint

指定通知方法中的参数;JoinPoint
JoinPoint:业务方法,需加入切面功能的业务方法
作用是:可以在通知方法中获取方法执行时的信息,例如方法名称,方法的实参
如果你的切面功能中需要用到方法的信息,就加入JoinPoint
这个JoinPoint参数的值是由框架赋值,必须是第一个参数的位置

@Before(value = "execution(* *..doSome(String,Integer))")
    public void MyBefore(JoinPoint jp){
        //获取方法的完整定义
        System.out.println("方法的签名(定义)="+jp.getSignature());
        System.out.println("方法的名称="+jp.getSignature().getName());

        //获取方法的实参
        Object[] args = jp.getArgs();
        for (Object arg : args) {
            System.out.println(arg);
        }

        //就是切面要执行的功能代码
        System.out.println("1前置通知,切面功能:在目标方法之前输出执行时间:"+new Date());
    }

3.@AfterReturning

@AfterReturning : 后置通知
属性: 1.value 切入点表达式
2.returning 自定义的变量,表示目标方法中的返回值
自定义方法的返回值,必须和后置通知方法的形参名一样
位置:在方法定义的上面
特点:
1.在目标方法之后执行的
2.能够获取到目标方法的返回值,可以根据这个放回值做不同的处理
Object res = doOther();
3.可以修改这个返回值,如果传入的是基本类型和String,修改后不影响程序的最终结果,如果是引用类型,修改后会改变最后输出的结果

  /**
     * 后置通知定义方法,方法是实现切面功能的
     * 方法的定义要求:
     * 1.公共方法 public
     * 2.方法没有返回值
     * 3.方法名称自定义
     * 4.方法可以有参数,
     */

@AfterReturning(value = "execution(* *..Some*.doOther2(String,Integer))",
            returning = "res" )
    public void myAfterReturning(Object res){

        System.out.println("后置通知,在目标方法执行之后,获取的返回值式:"+res);
        if(res != null){
            Student student = (Student)res;
            student.setAge(20);
            //修改后会改变最后的输出结果
            student.setName("jack");
        }
    }

目标类中的方法

@Override
    public Student doOther2(String name, Integer age) {
        Student student = new Student(name,age);

        return student;
    }

测试类

public class AppTest {
    @Test
    public void test01() {
        //创建spring容器
        ApplicationContext cs = new ClassPathXmlApplicationContext("applicationContext.xml");
        SomeService someService = (SomeService) cs.getBean("someService");
        Student student = someService.doOther2("tom", 2);
        System.out.println(student);
    }
}

运行结果

后置通知,在目标方法执行之后,获取的返回值式:Student{name='tom', age=2}
Student{name='jack', age=20}

4.@Around

@Around() 环绕通知
属性 value 是切入表达式,表示切入的功能
位置 : 在方法的上面
特点:
1.它是功能最强的通知
2.在目标方法的前后都能增强功能
3.控制目标方法是否被调用执行
4.修改原来的目标方法的执行结构 影响最后的结
环绕通知,等同于jdk动态代理的invocat
参数 : ProceedingJoinPoin
作用:执行目标方法的

返回值:就是目标方法的执行结果,可以被修改

/**
     *  环绕通知方法的定义格式
     * 方法的定义要求:
     * 1.公共方法 public
     * 2.方法必须有一个返回值,推荐使用Object
     * 3.方法名称自定义
     * 4.方法可以有参数,固定的参数 ProceedingJoinPoint
     */
      @Around(value = "execution(* *..doFirst(String,Integer))")
    public Object MyAround(ProceedingJoinPoint pjp) throws Throwable {
        //实现环绕通知
        Object result = null;
        System.out.println("环绕通知,在目标方法之前,输出时间:" + new Date());
        //1.目标方法调用
        //2.在目标方法前后都能添加功能
        result = pjp.proceed();//method.invoke;  Object result=doFirst
        if ("ab".equals(result)) {
            System.out.println("环绕通知,在目标方法之后,提交事务");
        }
        if(result != null){
            //修改返回值,回直接影响最后的返回值
            result = "hello aspect";
            return result;
        }
        return result ;
    }
}

5.@PointCut

@PointCut 定义和管理切入点,如果你的项目中有多个切入点表达式是重复的,可以复用的,
可以使用@PointCut
属性:value 切入点表达式
位置:在自定义的方法上面
特点:
当使用@PointCut定义在一个方法的上面,此时这个方法的名称就是切入点表达式
其他的通知中,value属性就可以使用这个方法,代表切入点表达式

@Before(value = "myPt()")
    public void MyBefore(){
        System.out.println("1前置通知,切面功能:在目标方法之前输出执行时间:"+new Date());
    }

    @After(value = "myPt()")
    public void MyAfter(){
        System.out.println("后置通知,在目标方法之后:");
    }
@Pointcut(value = "execution(* *..doSome(String,Integer))")
    public void myPt(){
        //无需代码
    }

5.@ After

最终通知,总是会被被执行的代码

  • 15
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

グ清晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值