最近了解到 SpringCache 这个组件,是用了 AOP 来消灭这样的重复代码:
public V queryList(){
if(Redis 缓存里有值){
return 值;
}else{
查数据库;
查询结果写入缓存;
}
}
使用 SpringCache 后,写法变成下面这样,与缓存打交道的代码就被放到运行时生成的代理类里去了:
@Cacheable
public V queryList(){
查数据库
}
}
看到这个组件的用法,我觉得很方便、灵活,我想请教的是,当工作中遇到类似需要写/封装组件的情况,应该怎么去思考,或者说解题框架是什么。
求大佬赐教!! orz
PS:没看到 SpringCache 前我也想过去消灭这种重复代码,但是我只知道一个很单一的目标:要把缓存相关操作提出来。关于怎么提、提完之后开发人员的使用方式(上面的使用方式就是注解 @Cacheable)完全没有思路。
1
jatesun 216 天前
其他的也可以用类似的方式,比如这种注解的形式,可以把日志也用这种方法写一下
|
2
Leviathann 216 天前 1
就是 decorator
|
3
azhong123 216 天前
@Leviathann 赞,非核心逻辑,装饰掉
|
4
murmur 216 天前
建议去找个开源的那种大而全的企业框架看一下,你能看到各种各样奇奇怪怪的注解
|
5
BiChengfei 216 天前 1
多看、多写、多想,工作久了,学会举一反三后,你就悟了
例如一个调用链:A --> B --> C --> D --> E ,那么我们绝对能在 A 调用 B 之间,做一些操作,日志?缓存?限流?编码?动态修改?参数篡改?参数防串改?熔断?......。每一个流程都是上一个流程的”网关“ 人类社会也是如此,A --> B --> C --> D --> E ,你把这些字母,想象成不同的人,在消息传达的过程中,你是否有机会做一些动作?保留消息?缓存消息?篡改消息,制造谣言?判断消息是否被篡改? |
6
BiChengfei 216 天前
人类社会,是最复杂的代码
|
7
huigeer 216 天前
先设计组件接口 interface ,然后再实现接口
|
8
lingalonely 216 天前
说白了,第一步是要提取共性,比如你说的加缓存,又比如你要加日志,这些都存在某种共性,再思考如何细分粒度,不同粒度设计会存在不同,既然是要提纯成组件,就要有合适的粒度,不能用一次改一次,能做到这些,一个基本的组件结构就出来,后面就是 bug 和性能的问题。
|
9
Hurriance 216 天前
可能有些偏题
仅是我个人的看法,我认为在工作中的代码应该需要保持统一的风格,框架、日志收集,开源框架带给我们的一大好处之一就是给大家做同样一件事达成了共识,对于每个人的阅读代码成本不会太高,除非是与业务深度绑定或者未有适用的开源框架,不然我不认为自己写一个组件是最优的选择,对于团队来讲,否则这样的做法在我看来只是为了满足工程师个人的成就感 |
10
iOCZS 216 天前
说白了就是让每个人可以少写代码
|
11
hitsmaxft 216 天前
aop 和注解/装饰器两者达到目的差别不大.无非差别就是通过扫描还是手动标注. 背后都是实现对应的 process, 加入对应的代码
如果你还不清楚怎么选择. 首先还是多写写框架. 通过包装的方式进行代码复用和增强, 从插件到 interpreter 再到 decorator, 最后就是字节码增强/代码生成这种黑魔法了 上来就 aop 和修饰器.很容易涉及不完善, 花了大力气, 后患无穷. |
13
k9990009 216 天前
为了偷懒,少写代码或者二次开发少改动。首先你要抽取业务需求的共性,区分出两部分,一部分是不变的,另一部分是变化的。不变的抽取出公共代码,变化的留出拓展口(允许自由实现或配置),与业务解耦。然后就是根据你已掌握的知识,设计不同的方案,考虑不同方案的优缺点,最终设计出一个最佳实践,想多了自然就会了。设计模式是让你更好的去维护你的代码。
|
14
cp19890714 216 天前
* 看现有的各种框架, 包含了什么思想, 利用了什么能力 来实现.
* 总结各种 思想 和 能力, 熟于心 * 下次遇到问题时, 套用. * 套用的多了, 形成思维惯性. |
15
wolfie 216 天前
试想为使用者,大胆的设计 API 使用方式 再考虑实现。
代码实现都是小事,外观设计好,内部实现代码垃圾点也无所谓,后面重构就行。 |
16
fkdtz 216 天前 1
个人有一个观点是不要过度设计,架构是演进出来的不是设计出来的。做一些可预见的设计优化是对的,但不要想的太多做的太早,否则你会发现要么设计的东西根本用不到、要么就是不符合业务发展需要不断重构。
回到问题,我认为封装的根本是分层思想。最基本的封装就是调用一个函数了,稍微进一步调用另一个文件中的函数,再如调用另一个包中的函数,再如调用另一个服务给你提供的函数,这些我认为都是分层,函数调用可以认为是陷入另一个层再回来,操作系统调用就是 trap 到内核层再回到用户层。 分层可以让你专注你自己的业务,其他的东西由别的层负责,例如限流、风控、鉴权、日志等都是与具体业务无关的通用的功能,就可以考虑封装为独立的一层。 到了具体实现环节我认为应该首先确定好接口,接口意味着协议,至少应该是一个在未来可以扩展的协议,这对分层来说是十分重要的,也意味着未来的修改没有历史包袱。另外应该尽量做到对业务无侵入性或尽量小,否则如果与业务有很强的耦合性就应该再思考一下是不是哪里不合理了。 |
17
Ashe007 216 天前 via iPhone
需要指出,SpringCache 并不能完全替换 Redis 缓存,因其是 jvm 的缓存,只是单机缓存,在多实例情况下会引发 bug 。你的问题也不太明确,或许你希望的是了解设计模式来指导组件的设计,常用的设计模式就那几种装饰器,代理,观察者……经常被提及的通常就是应用比较广泛的
|
18
Ashe007 216 天前 via iPhone
而且需要注意的是不能因设计模式强行提升项目复杂度,比如很多项目中过度抽象,毫无意义的 interface ,多余的策略模式
|
19
lizy0329 216 天前 1
终极的设计/封装的思路就是 sidecar 的概念,让业务人员始终关注业务:),其他都是透明层
|
20
dumbbell5kg OP 感谢各位的回复!挺有收获的
|