public class User {
private Integer id;
private String username;
private String note; public User(Integer id, String username, String note) {
this.id = id;
this.username = username;
this.note = note;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getNote() {
return note;
} public void setNote(String note) {
this.note = note;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", note='" + note + '\'' +
'}';
}
}

接口:

//@Component接口不用添加注入到容器,因为接口不能进行实例化
public interface UserService {
public void printUser(User user);
public void manyAspect();
}

实现类:

@Component
public class UserServiceImpl implements UserService { /**
* 这个方法将作为我们的AOP的接入点
* @param user
*/
@Override
public void printUser(User user) {
if (user.getUsername() == null){
throw new RuntimeException("检查用户参数是否为空。。。。");
}
System.out.println("id = "+ user.getId());
System.out.println("username = " + user.getUsername());
System.out.println("note = " + user.getNote());
} @Override
public void manyAspect() {
System.out.println("manyAspect------");
}
}
/**
* 定义切面
* @Aspect声明切面
*/
//@Aspect
public class MyAspect { //避免我们重复写一个表达式,引入了切入点概念PointCut,描述哪些类的哪些方法需要开启AOP编程。
@Pointcut("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))")
public void pointCut(){
} @Before("pointCut()")
public void before(){
System.out.println("before......");
} @After("pointCut()")
public void after(){
System.out.println("after......");
} @AfterReturning("pointCut()")
public void afterreturning(){
System.out.println("agterreturning.....");
} @AfterThrowing("pointCut()")
public void afterthrowing(){
System.out.println("afterthrowing.....");
} /**
* ProceedingJoinPoint类型参数,给参数的对象中有个方法proceed方法。回调原来的方法。
* @Around注解会取代原有目标的方法的通知。不进行回调得时候,方法是空的。
* @param joinPoint
* @throws Throwable
*/
@Around("pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("around before....");
//可以在这里打断点去查看joinPoint的内容
joinPoint.proceed();
System.out.println("around after....");
}
/**
* http://localhost:8080/aop/userprint?id=22&username=quan&note=huolala
* 有回调:
* around before...
* before......
* id = 22
* username = quan
* note = huolala
* agterreturning.....
* after......
* around after....
* ################
* 没回调:
* around before....
* around after....
*/ /**
* @DeclareParents作用:引入新的类来增强服务,
* value:指向你要增强功能的目标对象,这里要增强对象为UserServiceImpl对象
* defaultImpl:引入增强功能的类,UserValidatorImpl提供校验用户是否为空的
*/
@DeclareParents(value = "quan.springframework.springbootaop.aopdone.UserServiceImpl",defaultImpl = UserValidatorImpl.class)
public UserValidator userValidator; @DeclareParents(value = "quan.springframework.springbootaop.aopdone.UserServiceImpl",defaultImpl = UserValidatorIdImpl.class)
public UserValidatorId userValidatorId; /**
* 通知获取参数,
* && args(user)并将目标对象方法-名称为user的参数传递进来。
* @param joinPoint
* @param user
* 注意:
* JoinPoint类型的参数对于非环绕通知而言的参数。spring AOP自动传递到通知中
* 环绕通知自动你传递的参数为ProceedingJoinPoint类型的参数。
*/
@Before("pointCut() && args(user)")
public void beforeParam(JoinPoint joinPoint,User user){
Object[] args = joinPoint.getArgs();
System.out.println(args);
System.out.println("before param....");
} // @Before("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))")
// public void before(){
// System.out.println("before......");
// }
//
// @After("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))")
// public void after(){
// System.out.println("after......");
// }
//
// @AfterReturning("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))")
// public void afterreturning(){
// System.out.println("agterreturning.....");
// }
//
// @AfterThrowing("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))")
// public void afterthrowing(){
// System.out.println("afterthrowing.....");
// } /**
* execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))
* execution:表示执行时,拦截里面的正则匹配方法;
* *:表示任意返回类型的方法
* quan.springframework.springbootaop.aopdone.UserServiceImpl:指定目标对象的全限定类名
* printUser:指定目标对象的方法
* (**):表示任意参数进行匹配
*/ }

多切面:

/**
* 第一个切面
*/
@Order(3)
@Aspect
public class MyManyAop { @Pointcut("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.manyAspect(..))")
public void manyAspects(){
} @Before("manyAspects()")
public void before(){
System.out.println("MymanyAop1---before......");
} @After("manyAspects()")
public void after(){
System.out.println("MymanyAop1---after......");
} @AfterReturning("manyAspects()")
public void afterreturning(){
System.out.println("MymanyAop1---agterreturning.....");
} }
/**
* 第二个切面
*/
@Order(2)
@Aspect
public class MyManyAop2 { @Pointcut("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.manyAspect(..))")
public void manyAspects(){
} @Before("manyAspects()")
public void before(){
System.out.println("MymanyAop2---before......");
} @After("manyAspects()")
public void after(){
System.out.println("MymanyAop2---after......");
} @AfterReturning("manyAspects()")
public void afterreturning(){
System.out.println("MymanyAop2---agterreturning.....");
}
}
/**
* 第三个切面
*/
@Order(1)
@Aspect
public class MyManyAop3 { @Pointcut("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.manyAspect(..))")
public void manyAspects(){
} @Before("manyAspects()")
public void before(){
System.out.println("MymanyAop3---before......");
} @After("manyAspects()")
public void after(){
System.out.println("MymanyAop3---after......");
} @AfterReturning("manyAspects()")
public void afterreturning(){
System.out.println("MymanyAop3---agterreturning.....");
}
}

各个切面需要加入到容器当中:

@Configuration
public class AopConfiguration { /**
* 需要将切面加入到容器当中才能被织入
* @return
*/
@Bean("myAspect")
public MyAspect initMyAspect(){
return new MyAspect();
} /**
* 第一个切面
*/
@Bean("myManyAop")
public MyManyAop initMyManyAspect1(){
return new MyManyAop();
} /**
* 第二个切面
*/
@Bean("myManyAop2")
public MyManyAop2 initMyManyAspect2(){
return new MyManyAop2();
} /**
* 第三个切面
*/
@Bean("myManyAop3")
public MyManyAop3 initMyManyAspect3(){
return new MyManyAop3();
} }

通过类增强的:

/**
* 新建一个增强接口
*/
public interface UserValidator { public boolean validate(User user);
} /**
* 增强接口实现类
*/
public class UserValidatorImpl implements UserValidator { @Override
public boolean validate(User user) {
System.out.println("add validate");
return user.getUsername() != null;
}
}
public interface UserValidatorId {
public boolean idBigTWY(User user);
} public class UserValidatorIdImpl implements UserValidatorId{ @Override
public boolean idBigTWY(User user) {
System.out.println("UserValidatorId");
return user.getId() > 20;
}
}

什么是织入:

/**
* 织入:生成动态代理对象并且将切面和目标对象方法编织称为约定流程的过程
* Spring推荐的方式是接口+实现类的模式。
* spring支持JDK和CGLIB;
* JDK要求被代理对象必须拥有接口。
* CGLIB不做要求
* spring处理规则:当需要使用AOP的类拥有接口时,会以JDK动态代理运行,否则已CGLIB运行
* 注意:
* Spring 5.x 中 AOP 默认依旧使用 JDK 动态代理。
* SpringBoot 2.x 开始,为了解决使用 JDK 动态代理可能导致的类型转化异常而默认使用 CGLIB。
*/
@Controller
@RequestMapping("/aop")
public class AopController { @Autowired
UserService userService; @RequestMapping("/userprint")
@ResponseBody
public User pringUser(Integer id,String username,String note){
User user = new User(id,username,note);
userService.printUser(user);
return user;
}
/**
* request:
*http://localhost:8080/aop/userprint?id=22&username=quan&note=huolala
* result:
* before......
* id = 22
* username = quan
* note = huolala
* agterreturning.....
* after......
*/ @RequestMapping("/quote")
@ResponseBody
public User validateAndPrint(int id,String username,String note){
User user = new User(id,username,note);
//强制转换为UserValidator。
UserValidator userValidator = (UserValidator)userService;
if ( userValidator.validate(user) ){//判断是否为空user.username是否为空
userService.printUser(user);
} UserValidatorId userValidatorId = (UserValidatorId)userService;
if (userValidatorId.idBigTWY(user)){
System.out.println(user.getId());
}
return user;
} @RequestMapping("/many")
@ResponseBody
public String many(){
userService.manyAspect();
return "many aspect";
}
/**
* 顺序不一样的。
* MymanyAop1---before......
* MymanyAop2---before......
* MymanyAop3---before......
* manyAspect------
* MymanyAop3---agterreturning.....
* MymanyAop3---after......
* MymanyAop2---agterreturning.....
* MymanyAop2---after......
* MymanyAop1---agterreturning.....
* MymanyAop1---after......
*/ /**
* 加入Order:
* MymanyAop3---before......
* MymanyAop2---before......
* MymanyAop1---before......
* manyAspect------
* MymanyAop1---agterreturning.....
* MymanyAop1---after......
* MymanyAop2---agterreturning.....
* MymanyAop2---after......
* MymanyAop3---agterreturning.....
* MymanyAop3---after......
* 前置通知before都是从小到大运行,而后置通知和返回通知都是从大到小运行
* 典型的责任链模式顺序。
*/
}

spring-boot中的AOP的更多相关文章

  1. Spring Boot中使用AOP统一处理Web请求日志

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

  2. Spring Boot中使用AOP记录请求日志

    这周看别人写的springboot后端代码中有使用AOP记录请求日志,以前没接触过,因此学习下. 一.AOP简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编 ...

  3. 46. Spring Boot中使用AOP统一处理Web请求日志

    在之前一系列的文章中都是提供了全部的代码,在之后的文章中就提供核心的代码进行讲解.有什么问题大家可以给我留言或者加我QQ,进行咨询. AOP为Aspect Oriented Programming的缩 ...

  4. 转:Spring Boot中使用AOP统一处理Web请求日志

    在spring boot中,简单几步,使用spring AOP实现一个拦截器: 1.引入依赖: <dependency> <groupId>org.springframewor ...

  5. Spring boot中使用aop详解

      版权声明:本文为博主武伟峰原创文章,转载请注明地址http://blog.csdn.net/tianyaleixiaowu.       aop是spring的两大功能模块之一,功能非常强大,为解 ...

  6. (转)Spring Boot中使用AOP统一处理Web请求日志

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

  7. Spring Boot中自定义注解+AOP实现主备库切换

    摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...

  8. 56. spring boot中使用@Async实现异步调用【从零开始学Spring Boot】

    什么是"异步调用"? "异步调用"对应的是"同步调用",同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执 ...

  9. 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版

    欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...

  10. Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代理的问题

    Spring AOP底层的动态代理实现有两种方式:一种是JDK动态代理,另一种是CGLib动态代理. JDK动态代理 JDK 1.3版本以后提供了动态代理,允许开发者在运行期创建接口的代理实例,而且只 ...

随机推荐

  1. 使用Java的GUI技术实现 “ 贪吃蛇 ” 游戏

    详细教程: 使用Java的GUI技术实现 " 贪吃蛇 " 游戏_IT打工酱的博客-CSDN博客

  2. harbor服务器脚本

    项目实战,160服务器上安装harbor.mysql等 检查端口 check.sh #!/bin/bash echo -e "\033[31;1;4;5m check mysql... \0 ...

  3. 带你玩转CompletableFuture异步编程

    前言 最近在忙生活的第一个OKR,这个等等后面具体聊聊,今天开始恢复每周一篇原创,感谢小伙伴的不离不弃.这篇文章也是最近在Code Review的时候,看到的大家代码,想整体推下大家异步编程的思想,由 ...

  4. 企业为什么需要BI报表工具?

    企业一旦成规模运作起来,数据量是数以万计的,无论数据还是报表都需要协同管理不断更新.面对各大OA\ERP\CRM系统的数据,传统用Excel处理数据效率是很低下的.要想快速出报表,快速取数,快速做业务 ...

  5. C#爬虫(02):Web browser控件CefSharp的使用

    一.CefSharp介绍 CEF 全称是Chromium Embedded Framework(Chromium嵌入式框架),是个基于Google Chromium项目的开源Web browser控件 ...

  6. 编译安装nginx报错 checking for C compiler ... not found

    编译安装在执行./configure步骤报错,是因为缺少环境变量 checking for C compiler - not found ./configure: error: C compiler ...

  7. QT:Qt Creator快捷键与使用技巧

    功能 快捷键 解释 Switch Header/Source F4 在同名.h与.cpp文件间切换 Follow Symbol Under Cursor F2 跟踪光标下的变量或函数 变量:跟踪到变量 ...

  8. strtok:This function or variable may be unsafe.

    https://jingyan.baidu.com/article/49711c616b8a1ffa441b7cdc.html

  9. C# 字符串、数组和List的截取和转换

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...

  10. python面试_总结01_概念和内置高阶函数

    - 简答题 1.请谈谈Python中is 和 == 的区别(代码演示) is用于比较两个变量是否引用了同一个内存地址,is表示的是对象标识符(object identity),作用是用来检查对象的标识 ...