1. 程式人生 > 其它 >一個工作中碰到的小坑

一個工作中碰到的小坑

記錄一個小坑,開發壓測平臺的時候碰到的。

背景:現在在開發壓測平臺,抽象類一些常用攔截器作為 starter ,供所有 module 使用(目前我們有7個) 。starter 中使用的一些 entity, 使用了 Threadlocal ,用於儲存使用者資訊和部門資訊

問題:在 module 依賴了 starter 後,讀不到儲存在 Threadlocal 裡的使用者資訊,如 roleID,businessName。

過程: 攔截器和業務程式碼裡都加了以下列印 ThreadlocalMap 的程式碼來看看原因。

最後 double check 了一下,因為定義儲存在 Threadlocal 裡的 entity 類,存在不同的報名,被編譯器認為是兩個不同的類,所以是取不到的,破案。

這個和列印 Threadlocal 的程式碼沒什麼關係,不過學習到了很多 Threadlocal 的知識,學習一下。

記錄下來,作為警示。

以下是程式碼:

/**
* 我是列印ThreadLocalMap的分割線
*
*/

try {
//獲取當前執行緒物件
Thread thread = Thread.currentThread();
//獲取Thread中的threadLocals物件
Field threadLocals = Thread.class.getDeclaredField("threadLocals");
threadLocals.setAccessible(true);
//ThreadLocalMap是ThreadLocal中的一個內部類,並且訪問許可權是default
// 這裡獲取的是ThreadLocal.ThreadLocalMap
Object threadLocalMap = threadLocals.get(thread);

//這裡要這樣獲取ThreadLocal.ThreadLocalMap
Class threadLocalMapClazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
//獲取ThreadLocalMap中的Entry物件
Field tableField = threadLocalMapClazz.getDeclaredField("table");
tableField.setAccessible(true);
//獲取ThreadLocalMap中的Entry
Object[] objects = (Object[]) tableField.get(threadLocalMap);

//獲取ThreadLocalMap中的Entry
Class entryClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap$Entry");
//獲取ThreadLocalMap中的Entry中的value欄位
Field entryValueField = entryClass.getDeclaredField("value");
entryValueField.setAccessible(true);
//Entry繼承了WeakReference,WeakReference繼承了Reference
Field referEnceField = Reference.class.getDeclaredField("referent");
referEnceField.setAccessible(true);

Arrays.stream(objects).filter(obj -> obj != null).forEach((obj) -> {
try {
Object value = entryValueField.get(obj);
if (value != null) {
if (value instanceof Reference) {
Reference ref = (Reference) value;
log.info(ref.getClass().getName() + "------>" + ref.get());
} else {
log.info("------>" + value.getClass());
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
} catch (Exception e) {
e.printStackTrace();
}


/**
* 我是列印ThreadLocalMap的結束
*/