文档章节

Spring AOP 之三:通知(Advice)方法参数

trayvon
 trayvon
发布于 2017/06/30 20:28
字数 1226
阅读 287
收藏 0

简介

前面2篇文章我们重点介绍的是Spring AOP的流程和Pointcut表达式,我们处理一些简单的切面逻辑是没有问题了,在Pointcut表达式中介绍Pointcut表达式是为了在什么地方执行切面逻辑更加灵活,那么这篇文章介绍的通知参数处理就是为了让切面逻辑的做什么更加灵活。

JoinPoint

前面2篇介绍的切面逻辑基本上没有对被代理的逻辑本身做过多的操作,我们只是在被代理的逻辑(方法,连接点,Joinpoint)的前后执行切面逻辑。

如果我们要对被代理的逻辑(方法,连接点,Joinpoint)本身进行修改那应该怎么办呢?Spring AOP已经为我们提供了抽象Joinpoint。其实我们在前面的Around通知的时候已经简单的使用到了一点,不过使用的是Joinpoint的子类ProceedingJoinPoint。

我们可以通过Joinpoint来获取到代理的逻辑(方法,连接点,Joinpoint)的参数,代理对象(proxy),目标对象(target),方法签名等信息。

要使用JointPoint也很容易,会把JoinPoint对象传入代理方法(Advice方法,如@Before等通知注解的方法)的第一个参数。如果是Around通知出入的是ProceedingJoinPoint。

args

除了JoinPoint方式获取参数之外,还可以通过在Pointcut表达式中通过args绑定参数,并且还可以起到限制匹配参数的目的。

例如:

@Before("iAdviceParameter() && args(arg1,arg,..)")
public void joinPointParamterMethodBefore(String arg,Integer arg1){}

上面的表达式就可以把iAdviceParameter()匹配到的方法(Joinpoint,连接点)的参数传递到joinPointParamterMethodBefore方法中。注意匹配的方式只和args的顺序与类型相关,和joinPointParamterMethodBefore(Advice逻辑(方法))没有关系。

实例

上面的说明对于不是特别了解Spring AOP的同学可能过于抽象,所以下面还是通过一个实例来说明一下上面介绍的JoinPoint和args的用法。

下面的例子还是在原来之前的例子上进行了扩展,当然也可以单独的测试。下面还是先看一下目录结构。

目录结构

IAdviceParameter

public interface IAdviceParameter {
    
    String JoinPointParamterMethod(Integer arg1 ,String arg2,char arg3);

}

JoinPointParamterMethodImpl

import org.springframework.stereotype.Service;

import cn.freemethod.business.param.IAdviceParameter;

@Service
public class JoinPointParamterMethodImpl implements IAdviceParameter{

    @Override
    public String JoinPointParamterMethod(Integer arg1, String arg2,char arg3) {
        System.out.println(arg1);
        System.out.println(arg2);
        System.out.println(arg3);
        return "result";
    }

}

上面是2个业务逻辑相关的类,以便测试下面切面通知逻辑。

AdviceParameterAspect

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AdviceParameterAspect {
    
    @Pointcut("this(cn.freemethod.business.param.IAdviceParameter)")
    public void iAdviceParameter(){}
    
 //@Before("iAdviceParameter() && args(arg,arg1,..)")
    public void joinPointParamterMethodBefore(String arg1,Integer arg){
        System.out.println("AdviceParameterAspect Advice Before:"+arg1);
        System.out.println("AdviceParameterAspect Advice Before:"+arg);
    }
    
    @After("iAdviceParameter()")
    public void joinPointParamterMethodAfter(JoinPoint jp){
        System.out.println("AdviceParameterAspect Advice After...");
        Object[] args = jp.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
        System.out.println("kind:"+jp.getKind());
        System.out.println("target:"+jp.getTarget());
        System.out.println("proxy:"+jp.getThis());
        System.out.println("signature:"+jp.getSignature());
        System.out.println("AdviceParameterAspect Advice After...");
    }
    
//    @Around("iAdviceParameter()")
    public void joinPointParamterMethodAround(ProceedingJoinPoint pjp){
        System.out.println("AdviceParameterAspect Advice Around...");
        Object[] args = pjp.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
        System.out.println("AdviceParameterAspect Advice Around...");
    }
    
//    @Around("iAdviceParameter()")
    public Object joinPointParamterMethodAroundWithResult(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("AdviceParameterAspect Advice Around...");
        Object[] args = pjp.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
        System.out.println("AdviceParameterAspect Advice Around...");
        return pjp.proceed();
    }

}

上面是一个切面逻辑类,这里我们把Pointcut直接写在了切面之中了。通过上面的例子可以看到我们通过JoinPoint获取到参数数组,获取目标类(target),获取代理类(proxy)和方法签名。

下面我们重点看一下下面的方法:

 @Before("iAdviceParameter() && args(arg,arg1,..)")
    public void joinPointParamterMethodBefore(String arg1,Integer arg){
        System.out.println("AdviceParameterAspect Advice Before:"+arg1);
        System.out.println("AdviceParameterAspect Advice Before:"+arg);
    }

我们指定在上面的例子中Pointcut会匹配到下面的方法:

public String JoinPointParamterMethod(Integer arg1, String arg2,char arg3) 

在Spring执行切面逻辑(方法joinPointParamterMethodBefore)的时候,就会把调用JoinPointParamterMethod的参数和Pointcut中的args列表按位置匹配。和参数的名字无关之后参数的顺序有关,当args的参数和joinPointParamterMethodBefore参数匹配的时候就之后参数的名字有关和顺序无关。args(arg,arg1,..)中最后的的..表示还有其他参数。

AspectConfig

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {"cn.freemethod"})
public class AspectConfig {

}

上面是一个注解配置类。

AdviceParameterStart

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import cn.freemethod.business.param.IAdviceParameter;
import cn.freemethod.config.AspectConfig;


public class AdviceParameterStart {
    
    public static void main(String[] args) {
        AbstractApplicationContext  context = new AnnotationConfigApplicationContext(AspectConfig.class);
        IAdviceParameter bean = context.getBean(IAdviceParameter.class);
        String result = bean.JoinPointParamterMethod(1, "ok", 'c');
        System.out.println(result);
        context.close();
    }

}

上面一个是一个启动类。

注意:为了输出的清晰很多都是注释了,请根据实际要测试的方法取消注释。

参考

完整工程代码

Spring AOP 之一:基本概念与流程

Spring AOP 之二:Pointcut注解表达式

© 著作权归作者所有

trayvon
粉丝 16
博文 141
码字总数 214168
作品 1
程序员
私信 提问
Spring Aop配置时的切入点表达式

对应的中文: 任意公共方法的执行: execution(public (..)) 任何一个以“set”开始的方法的执行: execution( set(..)) AccountService 接口的任意方法的执行: execution( com.xyz.service...

cswy
2013/12/05
183
0
Spring 2.0 的AOP介绍及其通知类型

Spring 2.0的AOP 在Spring 2.0中最激动人心的增强之一是关于Spring AOP,它变得更加便于使用而且更加强大,主要是通过复杂而成熟的AspectJ语言的支持功能来实现,而同时保留纯的基于代理的J...

小星星程序员
2014/08/15
290
0
SpringAOP详细配置与使用

前言:本篇为复习总结之用,主要说明了下SpringAOP的概念,包含了Spring官方给的概念结合我自己的理解,配置其中包括了xml以及annotation方式。 SpringAOP简介: 面向切面编程(Aspect Orie...

菜鸟腾飞
01/05
0
0
使用Spring进行面向切面编程(AOP)

转载于http://www.blogjava.net/supercrsky/articles/174368.html 文章太长,写的很好,没看完,转过来慢慢理解,品味 简介 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方...

zmf
2014/09/04
1K
0
基于注解的Spring AOP的配置和使用

AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程。可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是G...

Zero零_度
2015/08/13
14.9K
0

没有更多内容

加载失败,请刷新页面

加载更多

总结:Linux

一、目录 目录 作用 /bin 存放二进制可执行文件(ls,cat,mkdir等),常用命令一般都在这里。 /etc /home 存放所有用户文件的根目录,是用户主目录的基点,比如用户user的主目录就是/home/user,...

浮躁的码农
23分钟前
4
0
什么是 happens-before 原则?

Java 中 happens-before 原则,是在 JSR-133 中提出的。 原文摘要: • Each action in a thread happens-before every subsequent action in that thread. • An unlock on a monitor happe......

ConstXiong
35分钟前
5
0
8核AMD Zen加持:微软Surface这回血拼

微软定于10月2日在纽约举办Surface新品发布会,几乎全线消费级产品都将更新,比如15英寸Surface Laptop 3。 最新爆料称,15寸Surface Laptop 3预计一口气推出6款型号,其中顶配为8核AMD处理器...

linuxCool
36分钟前
4
0
BeginnersBook MongoDB 教程

来源:ApacheCN BeginnersBook 翻译项目 译者:飞龙 协议:CC BY-NC-SA 4.0 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 请您勇敢地去翻译和改进翻译。虽然我们追求卓越,但我们并...

ApacheCN_飞龙
38分钟前
5
0
Java NIO:Buffer、Channel 和 Selector

本文将介绍 Java NIO 中三大组件 Buffer、Channel、Selector 的使用。 本来要一起介绍非阻塞 IO 和 JDK7 的异步 IO 的,不过因为之前的文章真的太长了,有点影响读者阅读,所以这里将它们放到...

乱世当空
39分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部