注解说明
@Aspect 声明一个切面
@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数
@Afrer、@Before、@Around参数的拦截规则为切点(PointCut),为了使切点复用,可使用@PointCut专门定义拦截规则,然后@Afrer等注解参数中调用
AspectJ表达式参考:http://dylanxu.iteye.com/blog/1312454
Spring本身在事务处理@Transacational和数据缓存@Cacheable上使用了此种方式拦截
编写拦截规则的注册
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Documented;
/**
* @author Kevin
* @description
* @date 2016/6/29
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
String name();
}
声明一个Service,使用注解拦截方式
import org.springframework.stereotype.Service;
/**
* @author Kevin
* @description 使用注解的被拦截类
* @date 2016/6/29
*/
@Service
public class DemoAnnotationService {
@Action(name = "注解式拦截的add操作")
public void add() {
}
}
声明另一个Service,使用方法规则拦截
import org.springframework.stereotype.Service;
/**
* @author Kevin
* @description 使用方法规则被拦截类
* @date 2016/6/29
*/
@Service
public class DemoMethodService {
public void add() {
}
}
编写切面
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* @author Kevin
* @description 切面类
* @date 2016/6/29
*/
// 注解声明一个切面
@Aspect
// 让该类成为spring容器管理的Bean
@Component
public class LogAspect {
// 通过@PointCut注解声明切点
@Pointcut("@annotation(ch01.aop.Action)")
public void annotationPointCut() {
}
// 通过@After注解声明一个建言,并使用@PointCut定义的切点
@After("annotationPointCut()")
public void after(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
// 通过反射获取注解上的树形,让后做日志记录相关操作
System.out.println("注解式拦截 " + action.name());
}
@AfterReturning(pointcut = "annotationPointCut()", returning = "returnVal")
public void afterReturning(JoinPoint joinPoint, Object returnVal) {
System.out.println("afterReturning executed, return result is "
+ returnVal);
}
@AfterThrowing(pointcut = "annotationPointCut()", throwing = "error")
public void afterThrowing(JoinPoint jp, Throwable error) {
System.out.println("error:" + error);
}
@Before("execution(* ch01.aop.DemoMethodService.*(..))")
public void before(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println("方法规则拦截," + method.getName());
}
@Around("annotationPointCut()")
public void around(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("around start");
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("around end");
}
}
配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @author Kevin
* @description
* @date 2016/6/29
*/
@Configuration
@ComponentScan("ch01.aop")
// 使用该注解开启spring对aspectj的支持
@EnableAspectJAutoProxy
public class Config {
}
运行
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author Kevin
* @description
* @date 2016/6/29
*/
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
DemoMethodService demoMethodService = context.getBean(DemoMethodService.class);
demoAnnotationService.add();
demoMethodService.add();
context.close();
}
}