Spring Aop切面

在springBoot中使用AOP需要引入:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

主要注解

这里写图片描述


切面表达式

这里写图片描述

  • *:匹配任意数量的字符
  • ..:一般用于匹配任意数量的子包或通配符
  • +:匹配指定类及其子类

    designators里面有很多方式,下面图片基本罗列了:
    这里写图片描述
    下面一一详细介绍:

    匹配包/类型 within

    如:

//匹配ProductService类里的所有方法
    @Pointcut("within(com.example.demo.MyAOp.service.ProductService)")
    public void adminonly2(){}
//匹配com.example.demo.MyAOp.service包及子包下所有方法
    @Pointcut("within(com.example.demo.MyAOp.service..*)")
    public void adminonly3(){}

匹配对象

  • 列表内容
    注:这里写图片描述

参数匹配

  • 列表内容

    注:图中标红的不可使用(会报错,不知道原因),需要缩小范围,如

//匹配ProductService中只有一个Long参数的方法
    @Pointcut("args(Long)&&within(com.example.demo.MyAOp.service.ProductService)")
    public void adminonly4(){}

匹配注解

  • -
//匹配标有MyAnnotation的类下的方法(不包括子孙类)/*注:缩小范围加上其它限制条件,不然可能报错,不知道为什么*/
    @Pointcut("@target(com.example.demo.MyAOp.myAnnocation.MyAnnotation)&&within(com.example.demo.MyAOp.service..*)")
    public void adminonly(){}

    //匹配标有MyAnnotation的类下的方法(包括子孙类)
    @Pointcut("@within(com.example.demo.MyAOp.myAnnocation.MyAnnotation)")
    public void adminonly2(){}

    //匹配标有MyAnnotation的方法
    @Pointcut("@annotation(com.example.demo.MyAOp.myAnnocation.MyAnnotation)")
    public void adminonly3(){}

    //匹配传入参数有MyAnnotation注解的方法
    @Pointcut("@args(com.example.demo.MyAOp.myAnnocation.MyAnnotation)")
    public void adminonly4(){}

execution表达式

  • -
 //匹配方法修饰符是public 返回值是*(任意返回值),com.example.demo.MyAOp.service包下
    //以Service结尾的类里的参数为任意的并且抛出Exception异常的delete方法
    @Pointcut("execution(public * com.example.demo.MyAOp.service.*Service.delete(..) throws Exception)")
    public void adminonly88(){}


//匹配方法修饰符是public 返回值是*(任意返回值),com.example.demo.MyAOp.service包下
    //以Service结尾的类里的参数为任意的delete方法
    @Pointcut("execution(public * com.example.demo.MyAOp.service.*Service.delete(..))")
    public void adminonly88(){}

advice注解

这里写图片描述

  • @Before
@Before("adminonly88()&&args(aa)")
    public void ceheck(Object aa){
        System.out.println("进入了AOP-------------------执行Before,接收参数= "+ aa);
    }

输出结果:进入了AOP-------------------执行Before,接收参数= 1
        这是一个删除的方法
  • @AfterReturning
@AfterReturning(value = "adminonly88()",returning = "aa")
    public void ceheck1(Object aa){
        System.out.println("进入了AOP-------------------执行After,返回结果="+ aa);
    }

输出结果:这是一个插入的方法
        进入了AOP-------------------执行After,返回结果=返回值
  • @Around
@Around("adminonly88()&&args(aa)")
    public void ceheck2(ProceedingJoinPoint joinPoint,Object aa){
        Object result = null;
        System.out.println("进入了AOP-------------------执行AfterReturning,接收参数= :"+ aa );
        try {
            result =joinPoint.proceed(joinPoint.getArgs());
            System.out.println("进入了AOP-------------------执行AfterReturning222 :" );
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("进入了AOP-------------------执行AfterReturning333,返回参数= "+result );

    }

输出结果:进入了AOP-------------------执行AfterReturning,接收参数= :1
        是一个删除的方法
        进入了AOP-------------------执行AfterReturning222 :
        进入了AOP-------------------执行AfterReturning333,返回参数= 返回值

实现原理

SpringAOP的实现是通过代理模式实现,通过jdk和Cglib的动态代理实现。
这里写图片描述
如何强制使用cglib代理呢?
这里写图片描述


注意事项

这里写图片描述

如何理解无法拦截内部方法调用???看下面例子


  • 这里写图片描述

如果直接调用getMenuList()方法,@Cacheable有效;若通过getRecommends()去调用的话,则@Cacheable无效。这是为什么呢?

  • this是没有经过AOP代理的bean, 而AOP的实现就是一个代理的增强。
  • 解决办法:改为走代理bean的方法。下面是具体操作:
    这里写图片描述

ApplicationContextHolder类的代码:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * Created by king on 2017-09-01
 */
@Component
public class ApplicationContextHolder implements ApplicationContextAware {

    private static ApplicationContext ctx;

    public static ApplicationContext getContext() {
        return ctx;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
    }
}

实现

请参考:http://blog.csdn.net/Kincym/article/details/77773220

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值