在springBoot中使用AOP需要引入:
<dependency>
<groupId>org.springframework.boot
</groupId>
<artifactId>spring-boot-starter-aop
</artifactId>
</dependency>
主要注解
切面表达式
*:匹配任意数量的字符..:一般用于匹配任意数量的子包或通配符
+:匹配指定类及其子类
designators里面有很多方式,下面图片基本罗列了: 下面一一详细介绍:
匹配包/类型 within
如:
@Pointcut(
"within(com.example.demo.MyAOp.service.ProductService)")
public void adminonly2(){}
@Pointcut(
"within(com.example.demo.MyAOp.service..*)")
public void adminonly3(){}
匹配对象
注:
参数匹配
注:图中标红的不可使用(会报错,不知道原因),需要缩小范围,如
@Pointcut(
"args(Long)&&within(com.example.demo.MyAOp.service.ProductService)")
public void adminonly4(){}
匹配注解
-
@Pointcut(
"@target(com.example.demo.MyAOp.myAnnocation.MyAnnotation)&&within(com.example.demo.MyAOp.service..*)")
public void adminonly(){}
@Pointcut(
"@within(com.example.demo.MyAOp.myAnnocation.MyAnnotation)")
public void adminonly2(){}
@Pointcut(
"@annotation(com.example.demo.MyAOp.myAnnocation.MyAnnotation)")
public void adminonly3(){}
@Pointcut(
"@args(com.example.demo.MyAOp.myAnnocation.MyAnnotation)")
public void adminonly4(){}
execution表达式
-
@Pointcut(
"execution(public * com.example.demo.MyAOp.service.*Service.delete(..) throws Exception)")
public void adminonly88(){}
@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