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(..))