Java 动态代理 & AOP
概述
AOP => Aspect Oriented Programming => 面向切面编程 => 关注一个统一的切面
OOP => Object Oriented Programming => 面向对象编程
AOP 适用于需要统一处理的场景
- 日志
- 缓存
- 鉴权
OOP 处理上述场景 => Decorator 装饰器模式
AOP
一般使用 Interface => 使用类,如果类里面有成员变量,继承类的时候都会拿到一份成员变量,有可能是没有用的,浪费空间 => interface 更加灵活,不会受到抽象类的限制
JDK 动态代理实现 AOP
java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy.newProxyInstance => 只有被代理的接口,未来被调用的时候才会进入到 InvocationHandler 的 invoke 方法中
优点:方便,不需要依赖任何第三方库
缺点:功能受限,只适用于接口
// TODO: example
CGLIB | ByteBuddy 字节码生成实现 AOP
优点:强大,不受接口限制
缺点:需要引用额外的第三方类库 + 不能增强 final 类 & final method & private method => 使用继承方式
Spring 中使用 AOP
spring-boot-starter-aop dependency => 默认使用 JDK 动态代理
CGLIB config => application.properties => spring.aop.proxy-target-class=true
-
@Aspect
=> 声明一个切面 -
@Configuration
=> 告知 Spring 当前类是用于生成和 Spring 有关的配置 -
@Before
=> 在开始一个方法之前 -
@After
=> 在结束一个方法之后 -
@Around
=> 将方法包裹起来 =>@Around("@annotation(xxx.anno.Cache)")
=> 参数org.aspectj.lang.ProceedingJoinPoint
// TODO: Spring boot AOP 实现 cache 缓存
Redis
广泛使用的内存缓存
启动 Redis => docker => docker redis => 默认端口映射 6379 => docker run --name first-redis -p 6379:6379 -d redis
Redis fast 原因
- 完全基于内存
- 优秀的数据结构设计
- 单一线程,避免上下文切换开销
- 事件驱动,非阻塞
Spring Boot Redis
@Bean
- 创建 RedisTemplate
-
@Autowired
RedisTemplate
Redis 存在最大的意义在于在多个机器分布式集群中共享数据
Java Object 序列化 => 字节流 => java.io.Serializable
Configuration
spring.redis.host=localhost // 本机
spring.redis.port=6379
spring boot redis starter
在 Spring Boot 中使用 Redis
- docker 启动 Redis 服务
- 配置 Redis Spring Boot starter
- 在 Spring 中配置 Redis
- 配置 Redis Template
@Configuration public class ApplicationConfig { @Bean RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } }
- 在使用的地方注入即可
知识点
- AOP 和 Spring 是不同的东西 => AOP 更多的使用场景是在 Spring 中,Spring 使得 AOP 变得更加强大
- 随机字符串 =>
UUID.randomUUID().toString()
- Spring 是如何切换 JDK 动态代理和 CGLIB 的 => 默认是 JDK 动态代理 => CGLIB 配置 =>
spring.aop.proxy-target-class=true
- 任何一个类只要实现了 java.io.Serializable interface 就可以开启序列化功能,使得 Java Object 自动的变成一个字节流
- Redis + Serializable Error => 找到拦截方法 => Redis 默认的序列化的库是 java.io.Serializable