1,创建自定义注解作为切点
/** * Copyright (c) 2015 www.sinorfc.com All Rights Reserved. */ package com.mango.online.basic.annotation; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.ElementType; /** * @version 1.0, 2015年6月17日 上午8:59:07 */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CacheAnnotation { } /** *定义一个之定义注解 * **/
2.在xml配置文件中添加aspectj支持
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <aop:aspectj-autoproxy/> </beans>
3.
定义拦截者并在配置文件声明拦截者和目标bean
@Aspect
public class LogInterceptor {
@Pointcut("execution(* regist*(..))||execution(* login*(..))")
private void log() {
}
//一个切面里使用 @Before 注解声明前置通知,在目标方法执行前执行
@Before("log()")
public void logInterceptor_before() {
System.out.println("Before LOG:"+" info has loged to file");
}
@After("log() && args(a)")
public void logInterceptor_after(String a) {
System.out.println("After LOG:"+a+" info has loged to file");
}
}
<bean id="regist" class="com.hss.sp.service.RegisterService"></bean>
//声明切面
<bean class="com.hss.sp.aop.LogInterceptor"></bean>
4编写执行类
/** * Copyright (c) 2015 www.sinorfc.com All Rights Reserved. */ package com.mango.online.basic.aspect; import java.util.HashMap; import org.apache.commons.lang.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.mango.core.logger.SimpleLogger; import com.mango.redis.RedisCacheService; /** * @author xuhuiwang * @version 1.0, 2015年6月17日 下午2:11:04 */ @Aspect // 该注解标示该类为切面类 @Component // 注入依赖 public class CacheAspect { private SimpleLogger logger = SimpleLogger.getLogger(this.getClass()); @Autowired private RedisCacheService redisCacheService; @Pointcut("@annotation(com.mango.online.basic.annotation.CacheAnnotation)") //使用自定义注解 @annotation(com.mango.online.basic.annotation.CacheAnnotation) /** *@annotation 在其他地方使用这个注解是就会执行这个类 *@annotation(com.mango.online.basic.annotation.CacheAnnotation) 注解中指定实现类的方式 **/ public void serviceAspect(){ } @Around(value = "serviceAspect()") public Object doCacheService(ProceedingJoinPoint pjp) throws Exception { //编写具体执行的业务代码 //pjp.proceed(); 使进程继续向下执行 return result; } }
注:通知类型
1前置通知
一个切面里使用 @Before 注解声明前置通知,在目标方法执行前执行
如:
@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
2后置通知
返回后通知通常在一个匹配的方法返回的时候执行。使用 @AfterReturning 注解来声明:
如:
@AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
3异常通知
抛出异常通知在一个方法抛出异常后执行。使用@AfterThrowing注解来声明:
如:
@AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doRecoveryActions() {
// ...
}
4最终通知
不论一个方法是如何结束的,最终通知都会运行。使用@After 注解来声明。最终通知必须准备处理正常返回和异常返回两种情况。通常用它来释放资源。
如:
@After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
public void doReleaseLock() {
// ...
}
5、环绕通知
最后一种通知是环绕通知。环绕通知在一个方法执行之前和之后执行。它使得通知有机会 在一个方法执行之前和执行之后运行。而且它可以决定这个方法在什么时候执行,如何执行,甚至是否执行。 环绕通知经常在某线程安全的环境下,你需要在一个方法执行之前和之后共享某种状态的时候使用。 请尽量使用最简单的满足你需求的通知。(比如如果简单的前置通知也可以适用的情况下不要使用环绕通知)。
环绕通知使用@Around注解来声明。通知的第一个参数必须是 ProceedingJoinPoint类型。在通知体内,调用 ProceedingJoinPoint的proceed()方法会导致 后台的连接点方法执行。proceed 方法也可能会被调用并且传入一个 Object[]对象-该数组中的值将被作为方法执行时的参数。
如:
@Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
当且点是在类上时而不是接口上请设置
<aop:aspectj-autoproxy proxy-target-class="true" />
<aop:aspectj-autoproxy />
参考网子:
http://blog.sina.com.cn/s/blog_5198c7370100hvxb.html
http://www.cnblogs.com/65702708/archive/2012/08/20/2647793.html
http://www.jianshu.com/p/8b95db8d7a1f
浙公网安备 33010602011771号