代理模式:动态地给一个对象添加一些额外的职责,它比生成子类方式更为灵活。

  • 优点:在某些时候装饰模式比继承(inheritance)要更加灵活

装饰模式的组成

(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类

(2)具体组件:将要被附加功能的类,实现抽象构件角色接口

(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口

(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。

应用场景

  • Spring Session
  • Mybatis的一级二级缓存
  • I/O 流(基于字符流[InputStream/OutputStream] 和 字节流[Reader/Writer]作为基类,eg:new FileInputStream(new File()),以下为Reader的类图)

装饰模式与责任链模式区别

责任链模式的实现原理

  • 每个被调用者都持有下一个被调用者的引用,客户端只需要发起第一个调用者即可完成所有的操作。
  • new A()-->new B()-->new C()====>A-->B-->C

装饰模式的实现原理

  • 持有被装饰的对象,需具备被装饰者的行为,对其行为进行补充增强
  • new A(new B(new C()))====>C-->B-->A

自定义注解实现多级缓存

a.注解定义

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExtJaryeCache {
}

b.注解使用

@RequestMapping("/getUser")
@ExtJaryeCache
public UserEntity getUser(Integer userId) {
return userMapper.findByUser(userId);
}

c.注解拦截

@Aspect
@Component
@Slf4j
public class ExtAsyncAop {
@Autowired
private JaryeCacheUtils jaryeCache; /**
* 使用Aop拦截我们的方法上是否使用缓存注解
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around(value = "@annotation(com.jarye.aop.ExtJaryeCache)")
public Object doAround(ProceedingJoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
// 获取目标方法
Method targetMethod = methodSignature.getMethod();
// // 拼接缓存的key
String key = targetMethod.getName() + Arrays.toString(targetMethod.getParameterTypes()) +
Arrays.toString(joinPoint.getArgs()); return jaryeCache.getCacheEntity(key,Object.class,joinPoint);
}
}

d.装饰模式核心方法

public <T> T getCacheEntity(String key,Class<T> t, ProceedingJoinPoint joinPoint) {
// 先查询二级缓存
T redisUser = redisUtils.getEntity(key, t);
if (redisUser != null) {
return (T) redisUser;
}
// 如果一级缓存存在数据
T jvmUser = super.getCacheEntity(key,t,joinPoint);
if (jvmUser == null) {
return null;
}
// 将该缓存数据放入到二级缓存中
redisUtils.putEntity(key, jvmUser);
return (T) jvmUser;
}
public <T> T getCacheEntity(String key, Class<T> t,ProceedingJoinPoint joinPoint) {
// 先查询我们的一级缓存(Jvm内置)
UserEntity jvmUser = JvmMapCacheUtils.getEntity(key, UserEntity.class);
if (jvmUser != null) {
return (T) jvmUser;
}
// 查询我们的db 通过aop直接获取到我们的目标对象方法
try {
Object resultDb = joinPoint.proceed();
// 数据库DB有的情况 将该内容缓存到当前Jvm中
JvmMapCacheUtils.putEntity(key, resultDb);
return (T) resultDb;
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
}

最新文章

  1. iOS 多线程GCD简介
  2. JavaScript 富文本编辑器
  3. 关于小组所要做的APP的想法
  4. HtmlAgilityPack---Html解析框架
  5. myeclipse中运行tomcat报错java.lang.NoClassDefFoundError
  6. 解决windows系统80端口被占用问题
  7. 非常不错的KPTimePicker效果源码
  8. 如何将angularJs项目与requireJs集成
  9. skynet网络库socket-server
  10. PyQt5创建第一个窗体(正规套路)
  11. C++ do while 0 使用和含义
  12. 测试SM图床
  13. Linux OpenGL 实践篇-2 创建一个窗口
  14. UNIX环境高级编程——线程同步之读写锁以及属性
  15. docker 基础知识分享ppt
  16. C#DataTable复制、C#DataTable列复制、C#DataTable字段复制
  17. (3)Python字符串
  18. 看完此文还不懂NB-IoT,你就过来掐死我吧...
  19. java 多样输入框
  20. vi/vim使用

热门文章

  1. vue父组件促发子组件中的方法
  2. Java学习的第五十二天
  3. 【Android Studio】安卓开发初体验1——安装与试用
  4. Git的全局及单个仓库配置
  5. Thinkphp3.2 cms之权限管理
  6. 18、Celery
  7. leetcode70word-search
  8. 幻读在 InnoDB 中是被如何解决的?(转)
  9. binary hacks读数笔记(nm命令)
  10. 删除ceph集群mds