目前所有的spring文章一律使用spring 4.2.4,包括前面的三篇
在前一篇中,代码里有一些@PointCut、@Before等的基本应用代码,而这次,我们将一起学习一下aop中的参数绑定、在此之前,我们先定义一个最基本的bean
@Component
public class HelloWorld {
public void sayHello (Data param){
System.out.println("Hello World! -> " + param.name);
}
}
在这个bean中、sayHello(Data)即我们要进行aop的方法、它有一个类型为Data的参数、Data也很简单
public class Data {
public String name;
public Data (String name){
this.name = name;
}
}
接下来定义切面
@Aspect
@Component
public class HelloWorldAspect {
@Before(value = "execution(* bindData.HelloWorld.sayHello(*)) && args(param2)")
private void beforeSayHello (Data param2){
System.out.println("this is before advice! -> " + param2.name);
param2.name = "change";
}
}
为了能使大家更好的理解、我特意没有将所有的参数均命名为param~~~
首先说明一点、sayHello(Data param)方法的参数名与切面中的args参数名完全没有关系。注意,我说的是参数名,而不是参数类型没关系。
下面我们逐一介绍上面@Before(value = "execution(* bindData.HelloWorld.sayHello(*)) && args(param2)")
@Before:表示前置通知。
value:匹配切点。
execution:声明具体的切点;此处表示取bindData包下HelloWorld类的sayHello方法、sayHello方法有且仅有一个参数,该方法可以返回任意的值。
args:匹配参数;在这里,param2首先匹配beforeSayHello方法中的param2参数,注意,这里是匹配名称相同的参数,然后取得param2的类型,为Data,表示匹配的sayHello(*)方法中的参数类型必须为Data,否则不予匹配。
最后,我们进行测试,当然还是全注解模式:
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "bindData")
public class AopConfig {
@Test
public void testBeforeSayHello (){
ApplicationContext ctx = new AnnotationConfigApplicationContext(AopConfig.class);
Data data = new Data("no change");
HelloWorld hw = ctx.getBean(HelloWorld.class);
hw.sayHello(data);
}
}
结果为
this is before advice! -> no change
Hello World! -> change
这样一来,我们就能实现在前置通知中改变被切方法的参数值了
还有一点需要注意:
it’s worth pointing out that this won’t work for generic collections. So you cannot define a pointcut like this:
@Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)")
public void beforeSampleMethod(Collection<MyType> param) {
// Advice implementation
}
意思是不支持范型集合,不要像上面这样使用