一、概述

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

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

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

二、使用

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. nginx.conf 详细

    ##定义nginx运行的用户各用户组user nginx nginx; ##nginx进程数,建议设置与cpu核心数一致worker_processes 1; ##全局错误日志定义类型[ debug ...

  2. NIO之直接缓冲区与非直接缓冲区

    直接缓冲区与非直接缓冲区的概念 一.非直接缓冲区 1)创建方式 通过 static ByteBuffer allocate(int capacity) 创建的缓冲区,在JVM中内存中创建,在每次调用基 ...

  3. NHibernate Transformers.AliasToEntityMap 返回Hashtable

    string query = "select a.CustomerName as CustomerName, b.ProductName as ProductName from Custom ...

  4. Redis命令学习-string类型操作

    APPEND key value     假设key已经存在,而且为字符串.那么这个命令会把value追加到原来值的末尾.假设key不存在.首先创建一个空字符串,再运行追加操作.     返回值:返回 ...

  5. Spring 新手教程(二) 生命周期和作用域

    以下的知识点是针对使用配置文件讲的(annotation相应标签后面文章会具体阐述) Bean的生命周期: 为什么关心这个问题? 我们使用IOC的目的就是为了让Spring IOC帮我们管理对象.从而 ...

  6. JavaScript Creating 对象

    可通过多种方法在 JavaScript 中创建你自己的对象.可以直接实例化Object 对象 (JavaScript),然后添加你自己的属性和方法.或者可以使用对象文本表示法来定义你的对象.还可使用构 ...

  7. Django的自定义标签

    Django提供了自定义标签功能,可以方便常用方法的重复使用. 标签的本质就是函数,标签名就是函数名. 注意点: 1.需要到django.template对象. 2.register = templa ...

  8. 用kaptcha生成验证码

    1.新建web项目,导入jar包:kaptcha-2.3.jar 2.配置web.xml代码如下: <?xml version="1.0" encoding="UT ...

  9. Java并发编程(六)发布与逸出

    "发布(Publish)"一个对象的意思指,使对象能够在作用域之外的代码中使用. 例如: 将一个指向该对象的引用保存到其他代码可以访问的地方 在一个非私有的方法中返回该引用 将引用 ...

  10. Android startActivity()和onActivityResult()使用总结(转载)

    有三个Activity: A.java ,B.java ,C.java Activity之间的跳转常用方法: 1. startActivity(Intent intent); 该方法只用于启动新的Ac ...