一、概述

  面向切面编程,将业务代码与处理琐碎相关度少的代码隔离开。以便达到重用,解耦。

  用途:日志记录、权限处理、性能统计、监控、事务处理、异常处理等

  通知类型有:前置通知、后置最终通知、后置返回通知、后置异常通知、环绕通知,

二、使用

1》增加POM依赖,默认已经启用aop,不需要增加注解等

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

2》创建一个Aspect切面类,并指定切点::

  封装横切关注点(日志,监控等),需要配置通知(前置通知,后置通知)和切入点(那些包哪些类的哪些方法等)

@Aspect
@Component
public class LogAspect {
  // 配置了com.lhx.spring.springboot.dao包及其子包下的所有类的所有方法
@Before("execution (* com.lhx.spring.springboot.dao..*.*(..))")
public void executeService() {
System.out.println("method executeService done");
}
}

2.1》前置通知 Before

    /**
* 前置通知,方法调用前被调用
* @param joinPoint
*/
@Before("executeService()")
public void doBeforeAdvice(JoinPoint joinPoint){
System.out.println("我是前置通知!!!");
//获取目标方法的参数信息
Object[] obj = joinPoint.getArgs();
//AOP代理类的信息
joinPoint.getThis();
//代理的目标对象
joinPoint.getTarget();
//用的最多 通知的签名
Signature signature = joinPoint.getSignature();
//代理的是哪一个方法
System.out.println(signature.getName());
//AOP代理类的名字
System.out.println(signature.getDeclaringTypeName());
//AOP代理类的类(class)信息
signature.getDeclaringType();
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
//如果要获取Session信息的话,可以这样写:
//HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
Enumeration<String> enumeration = request.getParameterNames();
Map<String,String> parameterMap = Maps.newHashMap();
while (enumeration.hasMoreElements()){
String parameter = enumeration.nextElement();
parameterMap.put(parameter,request.getParameter(parameter));
}
String str = JSON.toJSONString(parameterMap);
if(obj.length > 0) {
System.out.println("请求的参数信息为:"+str);
}
}

注意:这里用到了JoinPoint和RequestContextHolder。通过JoinPoint可以获得通知的签名信息,如目标方法名、目标方法参数信息等。通过RequestContextHolder来获取请求信息,Session信息。

2.2》后置返回通知

    /**
* 后置返回通知
* 这里需要注意的是:
* 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
* 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
* returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
* @param joinPoint
* @param keys
*/
@AfterReturning(value = "execution(* com.lhx.spring.springboot.dao..*.*(..))",returning = "keys")
public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
System.out.println("第一个后置返回通知的返回值:"+keys);
} @AfterReturning(value = "execution(* com.lhx.spring.springboot.dao..*.*(..))",returning = "keys",argNames = "keys")
public void doAfterReturningAdvice2(String keys){
System.out.println("第二个后置返回通知的返回值:"+keys);
}

调用方法

    public String testAfterReturning(String key){
return "key=: "+key;
}
public Integer testAfterReturning01(Integer key){
return key;
}

当入参key=testsss时

第一个后置返回通知的返回值:key=: testsss
第二个后置返回通知的返回值:key=: testsss

当入参key=55553时

第一个后置返回通知的返回值:55553

2.3》后置异常通知

    /**
* 后置异常通知
* 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
* throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
* 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
* @param joinPoint
* @param exception
*/
@AfterThrowing(value = "executeService()",throwing = "exception")
public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
//目标方法名:
System.out.println(joinPoint.getSignature().getName());
if(exception instanceof NullPointerException){
System.out.println("发生了空指针异常!!!!!");
}
}

2.4》后置最终通知

    /**
* 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
* @param joinPoint
*/
@After("executeService()")
public void doAfterAdvice(JoinPoint joinPoint){ System.out.println("后置通知执行了!!!!");
}

2.5》环绕通知

    /**
* 环绕通知:
* 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
* 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
*/
@Around("executeService()")
public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());
try {
Object obj = proceedingJoinPoint.proceed();
return obj;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}

三、AOP配置项

打开spring-boot-autoconfigure-1.5.9.RELEASE.jar查看包org.springframework.boot.autoconfigure.aop。AopAutoConfiguration

配置项:spring.aop.auto

@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)

  spring.aop.auto=true【默认】含义:启用aop

配置项:spring.aop.auto.proxy-target-class

@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = true)

  spring.aop.auto.proxy-target-class=false【默认】,含义:启用JdkDynamicAutoProxyConfiguration动态代理,代理接口,不能代理类

    注意如果代理的是类会自动切换至CglibAutoProxyConfiguration代理

  spring.aop.auto.proxy-target-class=true,含义:启用CglibAutoProxyConfiguration动态代理,代理接口和类

四、配置参数

1、默认也提供了:@EnableAspectJAutoProxy注解

    有两个参数:代理方式:proxyTargetClass 默认false,与上文一致

      exposeProxy:获取代理后对象,默认false。不支持。如果是true,可以通过AopContext.currentProxy()获取

2、后置注解增加参数

    @Before("execution (* com.lhx.spring.springboot.dao..*.*(..))")
public void logAfter(JoinPoint point) {
System.out.println("after log done," + point.getTarget().getClass()
+ ",args=" + Arrays.asList(point.getArgs())
+",method="+point.getSignature());
}

    

017-Spring Boot AOP的更多相关文章

  1. Spring Boot AOP解析

    Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspec ...

  2. Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理

    Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理   本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...

  3. 玩转spring boot——AOP与表单验证

    AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...

  4. Spring Boot - AOP(面向切面)

    AOP 全称 Aspect Oriented Programming(面向切面),AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分 ...

  5. spring boot aop打印http请求回复日志包含请求体

    一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  6. Spring boot AOP 记录请求日志

    如何将所有的通过url的请求参数以及返回结果都输出到日志中? 如果在controller的类中每个方法名都写一个log输出肯定是不明智的选择. 使用spring的AOP功能即可完成. 1. 在pom. ...

  7. redis分布式锁-spring boot aop+自定义注解实现分布式锁

    接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...

  8. Spring Boot AOP 扫盲,实现接口访问的统一日志记录

    AOP 是 Spring 体系中非常重要的两个概念之一(另外一个是 IoC),今天这篇文章就来带大家通过实战的方式,在编程猫 SpringBoot 项目中使用 AOP 技术为 controller 层 ...

  9. Spring Boot AOP

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...

  10. Spring boot Aop 示例

    需要的依赖 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -- ...

随机推荐

  1. Java线程安全同步容器

    线程安全同步容器(使用 synchronized关键字) 1.ArrayList->Vector,Stack 2.HashMap->HashTable(key.value不能为null) ...

  2. Atitit。sql2016标准化的规划方案 v3 q2a

    Atitit.sql2016标准化的规划方案 v3 q2a 1. Sql标准化的历史3 1.1. Sql92标准4 1.2. Sql99标准4 1.3. SQL:2003为例,它包括以下9个部分 5 ...

  3. Havel--Hakimi定理推断可图化 python

    介绍: 哈维尔[1955]--哈吉米[1962]算法能够用来判读一个度序列d是否是可图化的. 哈维尔[1955]--哈吉米[1962]定理: 对于N > 1,长度为N的度序列d可以可图化当且仅当 ...

  4. AV1视频编码标准资源汇总

    一直不看好HEVC,总觉得这东西绝对不可能再恢复像h264那么辉煌了,如此高昂的授权费,被淘汰估计也就这一两年了,有必要预研一下AV1,马上进去二进制码流冻结流程了,感觉aom越来越近了,毕竟goog ...

  5. Tomcat运行流程

    Connector介绍 1.1 Connector的种类 Tomcat源码中与connector相关的类位于org.apache.coyote包中,Connector分为以下几类: Http Conn ...

  6. Codeforces Round #404 (Div. 2) DE

    昨晚玩游戏竟然不小心错过了CF..我是有多浪啊. 今天总算趁着下课时间补了,感觉最后两题还是挺有意思的,写个题解. D: 题目大意: 给出一个括号序列,问有多少个子序列 是k个'(' + k个')' ...

  7. ASP.NET管道技术

    Asp.net mvc是基于dnf(.net framework )实现了代码分离的开源框架.ASP.NET MVC框架拥有极强的定制以及扩展的特性.本文梳理了ASP.NET MVC的管道(pipel ...

  8. CMakeList相关

    cmake使用示例与整理总结 http://blog.csdn.net/wzzfeitian/article/details/40963457/ 对应的demo:https://github.com/ ...

  9. excel添加复选框和去掉复选框

    添加复选框 我测试的excel版本是最新版2016,所有版本都是找开发者工具里面包含很多工具呢,大家可以慢慢测试 excel的右上角 点击文件-->选项-->自定义功能区-->添加开 ...

  10. urllib -- ProxyHandler处理器(代理设置)

    import urllib.requestimport randomimport ssl proxy_list = [ {"https" : "196.61.27.58: ...