@EnableAspectJAutoProxy 开启aop
Spring默认使用JDK代理 如果被代理者没有实现接口 则自动使用CGLib代理
@EnableAspectJAutoProxy(proxyTargetClass=true) 开启CGLib代理
===
@Aspect 标识该类是一个切面类
===
@Pointcut("bean(xxx)")
如果目标对象的beanId是xxx,那么为其创建代理对象(拦截类)
@Pointcut("within(com.jt.service.UserServiceImpl)") (拦截类)
@Pointcut("within(com.jt.service.*)") service包下所有类 不包括子包中的类
@Pointcut("within(com.jt.service..*)") Service包下所有类 包括子包中的类
@Pointcut("execution(返回值类型 包名.类名.方法名(参数类型))") (拦截方法)
@Pointcut("* execution(* com.jt.service..*.*(..))")
@Pointcut("* execution(* com.jt.service..*.add*(int))") 拦截add开头的方法 只有一个int参数
@Pointcut("execution(* com.jt.service.UserServiceImpl.add())")
@Pointcut("execution(* com.jt.service.UserServiceImpl.add(int,String))")
@Pointcut("@annotation(com.jt.anno.Zzh)") 通过自定义注解拦截 (拦截方法)
// @Pointcut("bean(userServiceImpl)")
// @Pointcut("within(com.jt.service.UserServiceImpl)")
// @Pointcut("within(com.jt.service.*)")
// @Pointcut("within(com.jt.service..*)")
// @Pointcut("execution(* com.jt.service.UserServiceImpl.addUser())") //只拦截addUser()
@Pointcut("@annotation(com.jt.anno.Zzh)")//通过自定义注解拦截
public void pointCut() {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Zzh {
}
@Service
public class UserServiceImpl implements UserService {
@Override
@Zzh
public void addUser() {
System.out.println("新增用户...");
}
}
@Before("xx()") 前置通知 在目标方法执行之前执行
在前置通知中,获取目标对象信息:
@Before("pointCut()")
public void before(JoinPoint joinPoint) {
System.out.println("前置通知开始===================");
Class<?> targetClass = joinPoint.getTarget().getClass();
String name = joinPoint.getSignature().getName();
String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName();
Object[] args = joinPoint.getArgs();
System.out.println("目标对象类型:"+targetClass);
System.out.println("拦截的方法名:"+name);
System.out.println("目标对象类名:"+declaringTypeName);
System.out.println("拦截方法的参数:"+ Arrays.toString(args));
System.out.println("前置通知结束===================");
}
===
@AfterReturning("xx()") 后置通知 在目标方法执行之后执行
在后置通知中,获取拦截方法的返回值,没有为null:
//后置通知:在目标方法执行之后执行
@AfterReturning(value="pointCut()",returning="result")
//通过 returning = "result" 获取目标方法返回值
public void afterReturn(Object result) {
System.out.println("后置通知...用户返回值:" + result);
}
===
@AfterThrowing("xx()") 异常通知 目标方法执行报错时执行
记录异常:
@AfterThrowing(value="pointCut()", throwing="exception")
public void afterThrowing(Exception exception) {
System.out.println("异常通知...获取异常信息:"+exception.getMessage());
// exception.printStackTrace();
}
===
@After("xx()") 最终通知 目标方法之后执行 不管目标方法是否报错
===
@Around("xx()") 环绕通知 目标方法执行前后都要执行 控制目标方法
测试:
public class MyTest {
@Test
public void test1() {
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean(UserService.class);
System.out.println(userService.getClass());
userService.addUser();
}
}
@Service
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("新增用户...");
}
}
@Service
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
System.out.println("新增用户...");
int a = 1/0;
}
}
@Order(1)
如果有多个切面类拦截同一个目标,那么按照@Order进行顺序执行
@Component
@Aspect
@Order(1)
public class SpringAOP2 {
@Around("@annotation(com.jt.anno.Zzh)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕bbbbbb");
Object result = joinPoint.proceed();
System.out.println("环绕bbbbbb");
return result;
}
}
@Component
@Aspect
@Order(2)
public class SpringAOP {
//...
}