代理模式:动态地给一个对象添加一些额外的职责,它比生成子类方式更为灵活。
- 优点:在某些时候装饰模式比继承(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;
}
}
相关文章链接:
<<<23中常用设计模式总览
<<<代理模式(Proxy Pattern)
<<<装饰模式(Decorator Pattern)
<<<观察者模式(Observer Pattern)
<<<单例模式(Singleton Pattern)
<<<责任链模式(Chain of Responsibility Pattern)
<<<策略模式(Strategy Pattern)
<<<模板方法模式(Template Pattern)
<<<外观/门面模式(Facade Pattern)
<<<建造者模式(Builder Pattern)
<<<适配器模式(Adapter Pattern)
<<<原型模式(Prototype Pattern)
<<<工厂相关模式(Factory Pattern)