惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
S
Secure Thoughts
月光博客
月光博客
美团技术团队
雷峰网
雷峰网
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Forbes - Security
Forbes - Security
W
WeLiveSecurity
P
Proofpoint News Feed
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
G
GRAHAM CLULEY
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
Last Week in AI
Last Week in AI
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Announcements
Recent Announcements
Webroot Blog
Webroot Blog
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
N
News and Events Feed by Topic
罗磊的独立博客
The Register - Security
The Register - Security
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
T
The Exploit Database - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
B
Blog
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Engineering at Meta
Engineering at Meta
Latest news
Latest news
IT之家
IT之家
D
DataBreaches.Net
博客园 - 司徒正美
N
Netflix TechBlog - Medium
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

犀利豆的博客

《SRE google 运维解密》读书笔记 (六) 《SRE google 运维解密》读书笔记 (五) 《SRE google 运维解密》读书笔记 (四) 《SRE google 运维解密》读书笔记 (三) 《SRE google 运维解密》读书笔记 (二) 《SRE google 运维解密》读书笔记 (一) 2021 总结 终于有一个 Java 可以用的微信机器人了 Vertx入门到实战—实现钉钉机器人内网穿透代理 钉钉机器人回调内网穿透代理--使用篇 周末补习(一)trie 树 那些有趣的代码(三)--勤俭持家的 ArrayList 那些有趣的代码(二)--偏不听父母话的 Tomcat 类加载器 那些有趣的代码(一)--有点萌的 Tomcat 的线程池 从需求第三定律说起--为什么知乎的回答质量下降了 如何利用 Spring Hibernate 高级特性设计实现一个权限系统 居然有人能忘记吃饭?写个微信机器人提醒他 我的2018年总结 从 LongAdder 中窥见并发组件的设计思路 徒手撸框架--实现 RPC 远程调用 我的写作工具链 Java 渲染 docx 文件,并生成 pdf 加水印 撸码的福音--变量名生成器的实现 Raft 协议学习笔记 dubbo 源码学习(一)开篇 Redis 命令的执行过程 Redis 中的事件驱动模型 Redis 数据库、键过期的实现 Redis 的基础数据结构(三)对象 Redis 的基础数据结构(二) 整数集合、跳跃表、压缩列表 Redis 的基础数据结构(一) 可变字符串、链表、字典 线程池 execute() 的工作逻辑 JAVA 中的 CAS 徒手撸框架--高并发环境下的请求合并 徒手撸框架--实现Aop 徒手撸框架--实现IoC 2017个人总结 Redis RedLock 完美的分布式锁么? JAVA 8入门(二)流 JAVA 8入门(一)Lambda表达式 有道 Alfred Workflow 威力加强版 Kafka实现原理笔记 《交易系统:更新与跨越》读后笔记 Netty-Apns接入实现 Future研究 Hystrix入门研究 Redis实现分布式锁
最近遇到的几个问题集合
Zhengxin Diao · 2017-11-29 · via 犀利豆的博客

最近在写项目的时候遇到了几个小问题,记录下来。希望对大家也有所帮助。

如何获取 T 的 class

在写BaseDao 之类的代码的时候,经常会遇到获取泛型T的class的情况?我们发现并没有T.class这种写法,那怎么办呢?想起之前写的Hibernate 里面有相关的代码。通过反射获取T的class

1
2
3
4
5
6
7
8
9
10
11
12
public class AbstractDao<T>{

private Class<T> clz;

public AbstractDao(){
this.clz = (Class<T>)
((ParameterizedType)getClass()
.getGenericSuperclass())
.getActualTypeArguments()[0];
}
...
}

Spring中的 @Value 加载时间

首先 @Value 注解可以方便的获取配置文件*.properties的参数。

在写代码的时候遇到这样一个问题。为了减少重复代码,我们通常需要写一个抽象类把共有的方法抽象到Abstract 类中。AbstractDao<T> 如果遇到需要向这个class的构造方法注入参数。且这个参数是通过抽象方法获取的。且这个数据是使用 Spring的 @Value 注解获取的。这个描述比较绕,我们直接看代码:

1
2
3
4
5
6
7
8
9
public class AbstractDao<T>{
private int tableId;

public AbstractDao(){
this.tableId = setTableId();
}

protected abstract int setTableId();
}
1
2
3
4
5
6
7
8
9
public class UserDao extends AbstractDao<User>{

@Value("${tableid.user}")
private int userTableId;

protected int setTableId() {
return buserTableId;
}
}

代码运行起来以后,我们发现 userTableId,并不能取到相应的值,这个时候@Value失效了。实际上这个问题的根源是因为@Value的加载是发生在对象实例化之后。也就是首先调用对象的构造函数,然后再获取配置文件中的数据。

解决的方案是使用注解 @PostConstruct,意思是构造函数执行完以后再执行注解标记的方法。我们可以吧抽象函数做如下修改:

1
2
3
4
5
6
7
8
9
10
public class AbstractDao<T>{
private int tableId;

@PostConstruct
public init(){
this.tableId = setTableId();
}

protected abstract int setTableId();
}

使用 Java 8 的 lambda 和 stream 来 merge List

在使用微服务架构以后。我们经常会遇到 Merge两个List的场景。比如我们从索引里面获取了一个 List<Long> 包含的是对象的ID的 list。由于前端对象展示的元素需要。用这个ID 的list分别从两个服务批量的查询得到 List<A>List<B>,然后将两个List合二为一成为一个List<C>,返回给前端作为列表页展示。

看代码:
首先我们有一个对象 A:

1
2
3
4
public class A{
private long id;
private String aStr;
}

有另一个对象 B:

1
2
3
4
public class B{
private long id;
private String bStr;
}

页面需要的对象C:

1
2
3
4
5
public class C{
private long id;
private String aStr;
private String bStr;
}

如何有效的把 List<A>List<B> merge 为一个 List呢?

总体思路,因为两个list从不同服务里面获取。有可能两个服务出于健壮性的考虑会抛弃某些查询不到的对象,所以两个list的长度有可能不一致。所以使用一个Map<Long,B> 作为索引。
如果直接写代码会相当繁琐。如果使用 Java 8 的新特性Lamabdastream api 就能快速写出代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

private C getCForAAndB(A a,B b){
C c = new C();
c.setId(a.getId());
c.setAstr(a.getAStr())
c.setBstr(b.getBStr())
return c;
}

private List<C> mergeList(List<A> aList,List<B> bList){

Map<Long,B> bMap = bList.parallelStream()
.collect(Collectors.toMap(B::getId,b -> b));

return aList.parallelStream()
.map(a -> getCForAAndB(a,bMap.get(a.getId)))
.collect(Collectors.toList());
}

这样merge的代码简洁明了。

如果不明白的同学可以参考我之前的 Java 8 教程。