spring-boot中的AOP
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¬e=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¬e=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的更多相关文章
- Spring Boot中使用AOP统一处理Web请求日志
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...
- Spring Boot中使用AOP记录请求日志
这周看别人写的springboot后端代码中有使用AOP记录请求日志,以前没接触过,因此学习下. 一.AOP简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编 ...
- 46. Spring Boot中使用AOP统一处理Web请求日志
在之前一系列的文章中都是提供了全部的代码,在之后的文章中就提供核心的代码进行讲解.有什么问题大家可以给我留言或者加我QQ,进行咨询. AOP为Aspect Oriented Programming的缩 ...
- 转:Spring Boot中使用AOP统一处理Web请求日志
在spring boot中,简单几步,使用spring AOP实现一个拦截器: 1.引入依赖: <dependency> <groupId>org.springframewor ...
- Spring boot中使用aop详解
版权声明:本文为博主武伟峰原创文章,转载请注明地址http://blog.csdn.net/tianyaleixiaowu. aop是spring的两大功能模块之一,功能非常强大,为解 ...
- (转)Spring Boot中使用AOP统一处理Web请求日志
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...
- Spring Boot中自定义注解+AOP实现主备库切换
摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...
- 56. spring boot中使用@Async实现异步调用【从零开始学Spring Boot】
什么是"异步调用"? "异步调用"对应的是"同步调用",同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执 ...
- 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版
欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...
- Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代理的问题
Spring AOP底层的动态代理实现有两种方式:一种是JDK动态代理,另一种是CGLib动态代理. JDK动态代理 JDK 1.3版本以后提供了动态代理,允许开发者在运行期创建接口的代理实例,而且只 ...
随机推荐
- [SuperSocket2.0]SuperSocket 2.0从入门到懵逼
SuperSocket 2.0从入门到懵逼 SuperSocket 2.0从入门到懵逼 1 使用SuperSocket 2.0在AspNetCore项目中搭建一个Socket服务器 1.1 引入Sup ...
- 【C# 基础概念】Unicode编码详解
Unicode定义:Unicode(统一码.万国码.单一码)是计算机科学领域里的一项业界标准,包括字符集.编码方案等.Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字 ...
- navicat12.0.24安装注意事项
关闭防火墙并断网,或者不要改变安装路径,或者换一个注册机 链接:https://pan.baidu.com/s/1AvEuD6TWGOCisSctF7pcbg 提取码:o4wp
- yum报错 , yum相关配置信息,yum重装
docker源的问题 yum有很多错,比如网络问题,dns问题,timeout 错,还有不知道什么错误 网上有很多,网络问题,dns问题,但是我ping www.baidu.com通,所以不是这个问题 ...
- html页面引用script出现中文乱码问题
在html的head标签中加入代码: <meta http-equiv="Content-Type" content="text/javascript; chars ...
- 面试中的MySQL主从复制|手撕MySQL|对线面试官
关注微信公众号[程序员白泽],进入白泽的知识分享星球 前言 作为<手撕MySQL>系列的第三篇文章,今天讲解使用bin log实现主从复制的功能.主从复制也是MySQL集群实现高可用.数据 ...
- Word:在文中插入对参考文献的引用
1.工具栏→插入→交叉引用 2."交叉引用"工具栏 引用类型:编号项: 引用内容:段落编号 选中要引用的参考文献编号 3.结果
- Excel VBA中写SQL,这些问题的方法你一定要牢记
小爬之前的文章 [Excel VBA中写SQL,这些问题你一定为此头痛过]中详细讲诉了一些常见的VBA 中使用SQL遇到的问题,这里再补充两个常见的问题场景及对应的解决方案,希望你们看了后能够思路开阔 ...
- JZ-040-数组中只出现一次的数字
数组中只出现一次的数字 题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 题目链接: 数组中只出现一次的数字 代码 /** * 标题:数组中只出现 ...
- SQL实现一年中每个日期剔除节假日和星期天之后的五个日期是多少
最近公司OA系统的需求,实现一年中每个日期剔除节假日和星期天之后的五个日期是几号,每个日期都要跳过节假日和星期天,当时是真的慌了,郁闷了一天,后来半夜忽然来灵感,想想还是可以实现. 需要做一张节假日的 ...