AOP:让你的代码像超级英雄一样飞翔

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: AOP:让你的代码像超级英雄一样飞翔

AOP


把这个过程细分为几个步骤


  1. 先写一个通知类 MyAdvice
  2. 写一个切入方法 并标记他是切入的通知 用Pointcut注解
Java
@Pointcut(“execution(* com.itheima.dao.BookDao.*d*(…))”)
private void pt(){}

其中括号里面的是切入点表达式


  1. 要在所有需要切入方法实际要操作的函数上添加@Around注解 括号里面是切入方法的名字
Java
@Around(“pt()”)
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(“------------------------------”);
Long startTime = System.currentTimeMillis();
for (int i = 0 ; i<10000 ; i++) {
//调用原始操作
pjp.proceed();
}
Long endTime = System.currentTimeMillis();
Long totalTime = endTime-startTime;
System.out.println(“执行万次消耗时间:” + totalTime + “ms”);
return null;
}
  1. 因为我们要使用Spring的功能 所以要让Spring知道 所以要让这个通知类被Spring扫描到 添加@Component注解
  2. 但是 Spring此时只会把他当普通的类看待 所以要告诉他这是在做通知操作 @Aspect
Java
@Component
Java
@Aspect
Java
public class MyAdvice {
  1. 最后要通知Spring 我们要启用AOP的模式去运行 所以要在配置类中 添加@EnableAspectJAutoProxy注解 来告诉Spring我们要使用上面那个@Aspect注解了
@Component
@Aspect
public class MyAdvice {

    @Pointcut("execution(* com.itheima.dao.BookDao.*d*(..))")
    private void pt(){}

    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("------------------------------");
        Long startTime = System.currentTimeMillis();
        for (int i = 0 ; i<10000 ; i++) {
            //调用原始操作
            pjp.proceed();
        }
        Long endTime = System.currentTimeMillis();
        Long totalTime = endTime-startTime;
        System.out.println("执行万次消耗时间:" + totalTime + "ms");
        return null;
    }

}


AOP工作流程


  1. Spring容器启动
  2. 读取所有切面配置中的切入点
  3. 初始化Bean 判定Bean对应的类中的方法是否匹配到任意切入点
  • 匹配失败 创建对象
  • 匹配成功 创建原始对象 (目标对象)的代理对象(这里内部使用的是jdk代理模式 )
  1. 获取Bean执行方法
  • 获取Bean调用方法并执行 完成操作
  • 获取的Bean是代理对象时 根据代理对象的运行模式运行原始方法与增强的内容 完成操作


AOP工作本质:代理模式


切入点表达式


Execution 执行

Java
@Pointcut(“execution(* com.itheima.dao.BookDao.*d*(…))”)
private void pt(){}


切入通知之 环绕通知***重要

@Around 表示这是个环绕通知 (在一前一后都有)

@Pointcut("execution(int com.itheima.dao.BookDao.select())")
private void pt2(){}//代表你的切入点在哪         在这呢↑

@Around("pt2()")//pjp代表原始操作
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("around before advice ...");
        //表示对原始操作的调用
        Object ret = pjp.proceed();//这里其实就是调用完原始操作的返回值
        System.out.println("around after advice ...");
        return ret;//返回值 因为原始操作函数要求要有返回值int
    }


原始操作函数:

Java
public interface BookDao {
public void update();

public int select();
}

AfterReturning

//@AfterReturning:返回后通知,在原始方法执行完毕后运行,且原始方法执行过程中未出现异常现象
 @AfterReturning("pt2()")
    public void afterReturning() {
        System.out.println("afterReturning advice ...");
    }


AfterThrowing

//@AfterThrowing:抛出异常后通知,在原始方法执行过程中出现异常后运行
@AfterThrowing("pt2()")
public void afterThrowing() {
    System.out.println("afterThrowing advice ...");
}


|写配置类 写完记得在Spring的配置类中导入|


最后!应用场景


  1. 日志记录: 通过AOP,在方法执行前后记录方法的输入参数、返回结果以及执行时间,从而实现统一的日志记录功能,避免在每个方法中都添加日志记录的代码。
  2. 权限控制: 在进入某些方法之前,进行用户权限的验证,确保用户有权执行这些方法。例如,在Web应用中,可以通过AOP拦截请求,并验证用户的登录状态和权限。
  3. 性能监控: AOP可用于监控程序的性能表现,例如统计某些关键方法的执行时间、调用次数等,帮助发现性能瓶颈。
  4. 事务管理: 通过AOP实现事务管理,确保在一系列数据库操作中的成功或失败都能得到正确处理,比如回滚所有操作或者提交事务。
  5. 异常处理: 使用AOP可以集中处理方法中出现的异常,统一记录异常信息或者执行特定的异常处理逻辑。
  6. 缓存控制: 通过AOP实现缓存的控制,比如在执行方法前检查缓存是否存在有效数据,如果存在则直接返回缓存数据。
  7. 国际化: AOP可用于统一处理国际化相关的逻辑,例如在方法调用前根据用户的语言偏好设置合适的国际化资源。
  8. 业务规则的验证: 在方法执行前进行业务规则的验证,确保业务逻辑的正确性,比如数据格式、业务逻辑等


在心理ai小程序这个业务中能用上的基本就是 语言偏好 后台的查询处理


用这个思想 写了一个登录效验器 用于校验那些需要用户登录才能使用的功能 的拦截监测


  1. 创建登录效验切面类: 创建一个切面类,用于实现登录效验逻辑。
|Java
@Aspect
@Component
public class LoginValidationAspect {
@Autowired
private StringRedisTemplate redisTemplate; // 使用Spring提供的StringRedisTemplate来操作Redis
@Pointcut(“execution(* com.yourpackage.controller.*.*(…)) && @annotation(com.yourpackage.annotation.RequireLogin)”)
public void loginRequired() {}
@Before(“loginRequired()”)
public void validateLogin(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String token = request.getHeader(“Authorization”); // 假设登录时会返回一个包含用户信息的Token
if (token == null || !redisTemplate.hasKey(token)) {
throw new UnauthorizedException(“用户未登录,请先登录”);
}
}
}|
| :- |

2. 创建自定义注解: 创建一个自定义注解,用于标记需要登录效验的方法。

Java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireLogin {
}
  1. 在Controller中使用自定义注解: 在需要进行登录校验的控制器方法上添加自定义注解。
Java
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping(“/login”)
public String login(@RequestBody LoginRequest request) {
// 处理登录逻辑
// …
return “登录成功”;
}
@RequireLogin
@GetMapping(“/user/info”)
public UserInfo getUserInfo() {
// 获取用户信息
// …
}
}
public UserInfo getUserInfo() {
// 获取用户信息
// …
}
}


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3月前
|
Java Maven 数据安全/隐私保护
代码优雅升级,提升开发效率:挖掘Spring AOP配置的学习宝藏!
代码优雅升级,提升开发效率:挖掘Spring AOP配置的学习宝藏!
|
8月前
|
监控 前端开发 Java
30个类手写Spring核心原理之AOP代码织入(5)
前面我们已经完成了Spring IoC、DI、MVC三大核心模块的功能,并保证了功能可用。接下来要完成Spring的另一个核心模块—AOP,这也是最难的部分。
38 0
|
10月前
|
设计模式 Java Spring
【Spring】核心部分之AOP:通过列举代码例子,从底层刨析,深入源码,轻轻松松理解Spring的核心AOP,AOP有这一篇足以
【Spring】核心部分之AOP:通过列举代码例子,从底层刨析,深入源码,轻轻松松理解Spring的核心AOP,AOP有这一篇足以
|
11月前
|
设计模式 Java Spring
【Spring】核心部分之AOP:通过列举代码例子,从底层刨析,深入源码,轻轻松松理解Spring的核心AOP,AOP有这一篇足以
【Spring】核心部分之AOP:通过列举代码例子,从底层刨析,深入源码,轻轻松松理解Spring的核心AOP,AOP有这一篇足以
一起谈.NET技术,利用AOP重构代码
  AOP是什么?    AOP是OOP的延续,Aspect Oriented Programming的缩写,即面向方面编程。AOP是GoF设计模式的延续,设计模式追求的是调用者和被调用者之间的解耦,AOP也是这种目标的一 种实现。
724 0
|
Java Spring
spring aop代码的增强
这篇博客,主要会分析spring aop是如何实现代码增强的。 从上一篇博客 我们大概知道,spring能在不改变代码的前提下,往一个方法的之前和之后添加代码。
1393 0
|
Java Spring
AOP动态代理解析2-代码织入入口
通过自定义配置完成了对AnnotationAwareAspectJAutoProxyCreator类型的自动注册,那么这个类到底做了什么工作来完成AOP的操作呢?首先我们看看AnnotationAwareAspectJAutoProxyCreator类的层次结构 在类的层级中,我们看到Annota...
704 0