Spring Aop切面

xiaoxiao2021-02-27  153

在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

转载请注明原文地址: https://www.6miu.com/read-17263.html

最新回复(0)