SpringAOP 处理通知中的参数(注解与xml配置)

  上一篇文章讲的是springaop的最基本配置,没有任何参数,有参数的也就在环绕通知@Around 中使用了ProceedingJoinPoint 作为参数,要是切面所通知的方法确实有参数该怎么办?下面通过一个需求来实现aop处理参数的功能。

需求

一个马戏团里有很多演员,编号分别为A、B、C…,老板要记录每个演员的演出次数作为年底发红包的依据。

  如果我们让演员去记录自己的演出次数,是可以的,但是你防不了一些歪心眼的演员故意提高自己的演出次数或者有时候演出太着急就会漏记次数。所以这里我们可以让老板聘请一位专门记录演员演出次数的“记录员”这样就绝对不会出错了。
  
  接下来我们用springAOP来实现这一需求,同样,本文给出两种写法注解式和xml配置的方式。

注解

重写接口

接上文,我们在Performance 里添加一个方法plackTrack(String number) 代码如下

package com.springinaction.service;
public interface Performance {
    public void perform();
    public void plackTrack(String number);
}

注意,这里包含参数number 为演员的编号。

实现接口

这里依然使用Actor 来实现接口,如下

package com.springinaction.service;

import org.springframework.stereotype.Component;

@Component
public class Actor implements Performance {

    @Override
    public void perform() {
        System.out.println("表演中...");
    }

    @Override
    public void plackTrack(String number) {
        System.out.println(number + " number actor");
    }

}
编写参数切面
package com.springinaction.aop;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TrackCountAnnotation {
    private Map<String,Integer> trackCounts = new HashMap<String,Integer>();

    @Pointcut("execution(** com.springinaction.service.Performance.plackTrack(String)) && args(trackNumber)")
    public void trackPlayed(String trackNumber){}

    @Before("trackPlayed(trackNumber)")
    public void countTrack(String trackNumber){
        System.out.println("i am record..." + trackNumber + " people");
        int currentCount = getPlayCount(trackNumber);
        trackCounts.put(trackNumber, ++currentCount);
    }

    public int getPlayCount(String trackNumber) {
        return trackCounts.get(trackNumber)!=null?trackCounts.get(trackNumber):0;
    }

}

这里注意切点表达式,
这里写图片描述
比普通的aop多了参数的类型和参数名,这里定义了Map<String,Integer> 来存演员的编号和对应的演出次数,这边就只加了一个@Before 的注解,意思就是演员在演出之前将其次数加一,没有对演出失败或者其他意外的情况做处理,可以使用@AfterReturning@AfterThrowing 处理。

编写测试类
package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.springinaction.aop.TrackCountAnnotation;
import com.springinaction.service.Actor;

public class ShowTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-annotation.xml");
        Actor actor = (Actor)context.getBean("actor");
        TrackCountAnnotation tc = (TrackCountAnnotation) context.getBean("trackCountAnnotation");
        actor.plackTrack("A");
        actor.plackTrack("B");
        actor.plackTrack("B");
        actor.plackTrack("C");
        actor.plackTrack("C");
        actor.plackTrack("C");
        actor.plackTrack("D");
        actor.plackTrack("D");


        System.out.println("A------> " + tc.getPlayCount("A"));
        System.out.println("B------> " + tc.getPlayCount("B"));
        System.out.println("C------> " + tc.getPlayCount("C"));
        System.out.println("D------> " + tc.getPlayCount("D"));
        System.out.println("E------> " + tc.getPlayCount("E"));
        System.out.println("F------> " + tc.getPlayCount("F"));
        System.out.println("G------> " + tc.getPlayCount("G"));
    }
}

输出为

i am record...A people
A number actor
i am record...B people
B number actor
i am record...B people
B number actor
i am record...C people
C number actor
i am record...C people
C number actor
i am record...C people
C number actor
i am record...D people
D number actor
i am record...D people
D number actor
A------> 1
B------> 2
C------> 3
D------> 2
E------> 0
F------> 0
G------> 0

这样就通过注解的方式来实现开头的需求,下面是xml配置。

XML配置

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

    <bean id="oldClown" class="com.springinaction.service.OldClown" />

    <bean id="trackCountXml" class="com.springinaction.aop.TrackCountXml" />

    <aop:aspectj-autoproxy proxy-target-class="true" />

    <aop:config>
        <aop:aspect id="aspect" ref="trackCountXml">
            <aop:pointcut
                expression="execution(** com.springinaction.service.Performance.plackTrack(String)) and args(trackNumber)"
                id="trackPlayed" />
            <aop:before method="countTrack" pointcut-ref="trackPlayed" />
        </aop:aspect>
    </aop:config>

</beans>

这里需注意xml文件中切点表达式的写法,&& 要使用and 代替。

编写参数切面
package com.springinaction.aop;

import java.util.HashMap;
import java.util.Map;

public class TrackCountXml {
    private Map<String,Integer> trackCounts = new HashMap<String,Integer>();

    public void trackPlayed(String trackNumber){}

    public void countTrack(String trackNumber){
        System.out.println("i am record..." + trackNumber + " people");
        int currentCount = getPlayCount(trackNumber);
        trackCounts.put(trackNumber, ++currentCount);
    }

    public int getPlayCount(String trackNumber) {
        return trackCounts.get(trackNumber)!=null?trackCounts.get(trackNumber):0;
    }

}
编写测试类
package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.springinaction.aop.TrackCountXml;
import com.springinaction.service.OldClown;

public class ShowTestXml {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-arg-xml.xml");
//      OldClown oldClown = (OldClown)context.getBean("oldClown");// TODO
//      // http://www.cnblogs.com/liuling/p/2014-8-23-001.html
//      oldClown.perform();
        OldClown oldClown = (OldClown)context.getBean("oldClown");
        TrackCountXml tc = (TrackCountXml) context.getBean("trackCountXml");
        oldClown.plackTrack("A");
        oldClown.plackTrack("B");
        oldClown.plackTrack("B");
        oldClown.plackTrack("C");
        oldClown.plackTrack("C");
        oldClown.plackTrack("C");
        oldClown.plackTrack("D");
        oldClown.plackTrack("D");


        System.out.println("A------> " + tc.getPlayCount("A"));
        System.out.println("B------> " + tc.getPlayCount("B"));
        System.out.println("C------> " + tc.getPlayCount("C"));
        System.out.println("D------> " + tc.getPlayCount("D"));
        System.out.println("E------> " + tc.getPlayCount("E"));
        System.out.println("F------> " + tc.getPlayCount("F"));
        System.out.println("G------> " + tc.getPlayCount("G"));
    }
}

输出的结果和上面是一样的。
因为项目很小就没有放到Git上托管,下面将文件下载地址

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值