SpringAOP注解

 @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 {
    //...
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值