Spring AOP的使用 基于全注解AspectJ

1.切面

package com.zghw.spring.demo.demo.aop.aspect;

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

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import com.zghw.spring.demo.demo.aop.pojo.Giftcard;
import com.zghw.spring.demo.demo.aop.service.GiftcardService;

/**
 * 定义切面
 * 
 * @author zghw
 *
 */
@Aspect
@Component
public class GiftcardAspect {
	// 用来缓存查询到的giftCard
	private final Map<String, Object> cardCache = new HashMap<String, Object>();

	@Pointcut("execution(public * com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl.findByCardNo(String)) && args(cardNo)")
	public void findByCardNo(String cardNo) {
	}

	/**
	 * 前置通知
	 * 
	 * @param cardNo
	 */
	@Before(value = "findByCardNo(cardNo)")
	public void findByCardNoCacheBefore(String cardNo) {
		System.out.println("前置通知:开始尝试从缓存中取:" + cardNo);
		if (cardCache.containsKey(cardNo)) {
			System.out.println("存在缓存中" + cardNo);
		} else {
			System.out.println("不存在缓存中" + cardNo);
		}
	}

	/**
	 * 在findByCardNo加入缓存
	 */
	// @AfterReturning(pointcut="findByCardNo(cardNo)",returning="retVal")
	// 或者使用
	@AfterReturning(value = "execution(public * com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl.findByCardNo(String)) && args(cardNo)", argNames = "cardNo,retVal", returning = "retVal")
	public Giftcard findByCardNoCache(String cardNo, Giftcard retVal) {
		if (!cardCache.containsKey(cardNo)) {
			System.out.println("后置通知:不存在就加入缓存中" + cardNo);
			cardCache.put(retVal.getCardNo(), retVal);
		}
		return retVal;
	}

	/**
	 * JoinPoint可以在任何通知方法中作为第一个参数使用,可以用来访问加入点的很多信息。
	 * 
	 * @param joinPoint
	 */
	@After(value = "execution(* com.zghw.spring.demo.demo.aop.*.*.findByCardNo(..))")
	public void findByCardNoCacheAfter(JoinPoint joinPoint) {
		System.out.println("最后通知,已经完成。");
		System.out.println("来看看这个对象JoinPoint有什么作用");
		Object target = joinPoint.getTarget();
		System.out.println("目标对象:" + target);
		System.out.println("目标对象类型:" + target.getClass());
		if (target instanceof GiftcardService) {
			GiftcardService gs = (GiftcardService) target;
			// 使用目标类型调用其他方法
			System.out.println(gs.findByCardNo("2222222"));
		}
		Object[] args = joinPoint.getArgs();
		System.out.println("参数:长度" + args.length);
		int i = 0;
		for (Object arg : args) {
			System.out.println("参数" + (++i) + " :类型" + arg.getClass());
		}
		Object proxy = joinPoint.getThis();
		System.out.println("这个得到代理对象 " + proxy);
		System.out.println("得到代理对象类型 " + proxy.getClass());
		System.out.println("从这里可以看出来它代理的是GiftcardService == "
				+ (proxy instanceof GiftcardService));
		System.out.println("方法签名:" + joinPoint.getSignature());
		System.out.println(joinPoint.getSourceLocation());
		System.out.println(joinPoint.getKind());
		System.out.println(joinPoint.getStaticPart().toShortString());
	}

	/**
	 * 前置通知和后置通知不再一起很难控制目标对象调用方法, 比如前置方法判断出了该对象在缓存中,能够取得值而不能返回值缓存中的对象。
	 * 后置方法虽然能够返回值,但是不能够在目标方法调用前返回值。 使用环绕通知就很好的解决问题。 环绕通知
	 * 
	 * @param giftcard
	 * @throws Throwable
	 */
	@Around(value = "findByCardNo(cardNo)")
	public Giftcard findByCardNoCacheAround(ProceedingJoinPoint pjp,
			String cardNo) throws Throwable {
		Giftcard card = null;
		System.out.println("Around:前置通知:开始尝试从缓存中取:" + cardNo);
		if (cardCache.containsKey(cardNo)) {
			System.out.println("Around:存在缓存中" + cardNo);
			// 如果缓存中存在就不需要从目标对象中取
			return (Giftcard) cardCache.get(cardNo);
		}
		card = (Giftcard) pjp.proceed();// 通过一个个通知方法拦截器链得到返回的对象。
		if (!cardCache.containsKey(card.getCardNo())) {
			System.out.println("Around:后置通知:不存在就加入缓存中" + cardNo);
			cardCache.put(card.getCardNo(), card);
		}
		return card;
	}

	/**
	 * 用来测试一个方法的执行时间
	 * 
	 * @param pjp
	 * @param giftcard
	 */
	@Around(value = "execution(* com.zghw.spring.demo.demo.aop.*.*.save(com.zghw.spring.demo.demo.aop.pojo.Giftcard)) and args(giftcard)", argNames = "giftcard")
	public void saveTime(ProceedingJoinPoint pjp, Giftcard giftcard) {
		StopWatch sw = new StopWatch();
		sw.start(giftcard.getDescription());
		try {
			pjp.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		sw.stop();
		System.out.println(sw.prettyPrint());
	}
}


2.目标类


package com.zghw.spring.demo.demo.aop.pojo;

public class Giftcard {
	private String name;
	private String cardNo;
	private double price;
	private String description;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCardNo() {
		return cardNo;
	}

	public void setCardNo(String cardNo) {
		this.cardNo = cardNo;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@Override
	public String toString() {
		return "Giftcard [name=" + name + ", cardNo=" + cardNo + ", price="
				+ price + ", description=" + description + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((cardNo == null) ? 0 : cardNo.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Giftcard other = (Giftcard) obj;
		if (cardNo == null) {
			if (other.cardNo != null)
				return false;
		}
		return true;
	}

}
package com.zghw.spring.demo.demo.aop.service;

import com.zghw.spring.demo.demo.aop.pojo.Giftcard;

public interface GiftcardService {
	
	public void save(Giftcard giftcard);

	public Giftcard findByCardNo(String cardNo);

	public Giftcard update(Giftcard giftcard);
}
package com.zghw.spring.demo.demo.aop.service.impl;

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

import org.springframework.stereotype.Component;

import com.zghw.spring.demo.demo.aop.pojo.Giftcard;
import com.zghw.spring.demo.demo.aop.service.GiftcardService;
@Component("giftcardService")
public class GiftcardServiceImpl implements GiftcardService {
	private final Map<String, Giftcard> giftcards = new HashMap<String, Giftcard>();

	public void save(Giftcard giftcard) {
		System.out.println("开始保存对象。。。。");
		giftcards.put(giftcard.getCardNo(), giftcard);
		try {
			//模拟一下时间
			Thread.sleep((int)(Math.random()*100));
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		};
		System.out.println("保存完成");
	}

	public Giftcard findByCardNo(String cardNo) {
		Giftcard giftcard = giftcards.get(cardNo);
		System.out.println("执行目标方法:findByCardNo");
		return giftcard;
	}

	public Giftcard update(Giftcard giftcard) {
		Giftcard card = giftcards.put(giftcard.getCardNo(), giftcard);
		return card;
	}

}

3.测试类

package com.zghw.spring.demo.demo.aop;

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

import com.zghw.spring.demo.demo.aop.pojo.Giftcard;
import com.zghw.spring.demo.demo.aop.service.GiftcardService;
@Configuration 
@ComponentScan
//激活AspectJ进行自动代理
@EnableAspectJAutoProxy
public class ApplicationAnnotation {

	public static void main(String[] args) {
		ApplicationContext ctx =new AnnotationConfigApplicationContext(ApplicationAnnotation.class);
		GiftcardService giftcardService = (GiftcardService) ctx
				.getBean("giftcardService");
		//模拟添加数据到数据库中
		Giftcard card = new Giftcard();
		card.setCardNo("11111111");
		card.setDescription("第一个对象");
		card.setName("zghw");
		card.setPrice(1322546.45);
		//模拟保存对象到数据库中
		giftcardService.save(card);
		Giftcard card2 = new Giftcard();
		card2.setCardNo("2222222");
		card2.setDescription("第二个对象");
		card2.setName("dfsdf");
		card2.setPrice(467732346.45);
		//模拟保存对象到数据库中
		giftcardService.save(card2);
		//模拟先从缓存中取去不到就去数据库中取值
		System.out.println("=======第一次==========");
		giftcardService.findByCardNo("11111111");
		System.out.println("=========第二次========");
		giftcardService.findByCardNo("11111111");
		System.out.println("=========第三次========");
		giftcardService.findByCardNo("11111111");
	}

}

4.输出结果

Mar 28, 2016 11:37:24 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3316f2e6: startup date [Mon Mar 28 11:37:24 CST 2016]; root of context hierarchy
开始保存对象。。。。
保存完成
StopWatch '': running time (millis) = 63
-----------------------------------------
ms     %     Task name
-----------------------------------------
00063  100%  第一个对象

开始保存对象。。。。
保存完成
StopWatch '': running time (millis) = 73
-----------------------------------------
ms     %     Task name
-----------------------------------------
00073  100%  第二个对象

=======第一次==========
Around:前置通知:开始尝试从缓存中取:11111111
前置通知:开始尝试从缓存中取:11111111
不存在缓存中11111111
执行目标方法:findByCardNo
Around:后置通知:不存在就加入缓存中11111111
最后通知,已经完成。
来看看这个对象JoinPoint有什么作用
目标对象:com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl@62214c6f
目标对象类型:class com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl
执行目标方法:findByCardNo
Giftcard [name=dfsdf, cardNo=2222222, price=4.6773234645E8, description=第二个对象]
参数:长度1
参数1 :类型class java.lang.String
这个得到代理对象 com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl@62214c6f
得到代理对象类型 class com.sun.proxy.$Proxy16
从这里可以看出来它代理的是GiftcardService == true
方法签名:Giftcard com.zghw.spring.demo.demo.aop.service.GiftcardService.findByCardNo(String)
org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@36db33f6
method-execution
execution(GiftcardService.findByCardNo(..))
=========第二次========
Around:前置通知:开始尝试从缓存中取:11111111
Around:存在缓存中11111111
最后通知,已经完成。
来看看这个对象JoinPoint有什么作用
目标对象:com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl@62214c6f
目标对象类型:class com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl
执行目标方法:findByCardNo
Giftcard [name=dfsdf, cardNo=2222222, price=4.6773234645E8, description=第二个对象]
参数:长度1
参数1 :类型class java.lang.String
这个得到代理对象 com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl@62214c6f
得到代理对象类型 class com.sun.proxy.$Proxy16
从这里可以看出来它代理的是GiftcardService == true
方法签名:Giftcard com.zghw.spring.demo.demo.aop.service.GiftcardService.findByCardNo(String)
org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@7130779c
method-execution
execution(GiftcardService.findByCardNo(..))
=========第三次========
Around:前置通知:开始尝试从缓存中取:11111111
Around:存在缓存中11111111
最后通知,已经完成。
来看看这个对象JoinPoint有什么作用
目标对象:com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl@62214c6f
目标对象类型:class com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl
执行目标方法:findByCardNo
Giftcard [name=dfsdf, cardNo=2222222, price=4.6773234645E8, description=第二个对象]
参数:长度1
参数1 :类型class java.lang.String
这个得到代理对象 com.zghw.spring.demo.demo.aop.service.impl.GiftcardServiceImpl@62214c6f
得到代理对象类型 class com.sun.proxy.$Proxy16
从这里可以看出来它代理的是GiftcardService == true
方法签名:Giftcard com.zghw.spring.demo.demo.aop.service.GiftcardService.findByCardNo(String)
org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@24fcdcd2
method-execution
execution(GiftcardService.findByCardNo(..))




你可能感兴趣的:(Spring AOP的使用 基于全注解AspectJ)