国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Java Cache詳解及簡單實現(xiàn)

Java Cache詳解及簡單實現(xiàn)

2020-08-03 15:09EthanPark Java教程

這篇文章主要介紹了 Java Cache詳解及簡單實現(xiàn)的相關(guān)資料,需要的朋友可以參考下

 Java Cache詳解及簡單實現(xiàn)

概要:

最近在做spring的項目,想做一個緩存,訪問數(shù)據(jù)庫,定期來做數(shù)據(jù)更新

要實現(xiàn)兩個功能

  1. 可以通過http請求來立刻刷新緩存
  2. 緩存可以通過自己配置的時間間隔來定期刷新

通過Controller來做

因為需要通過http來刷新緩存,所以第一個想法就是把緩存做成一個Controller

Controller的實現(xiàn)

Controller最大的優(yōu)勢,就是可以通過Spring的配置,注入很多依賴,比如對Service的依賴,對數(shù)據(jù)庫的依賴等。

大量的訪問數(shù)據(jù)庫跟服務(wù)層的代碼,都可以進行復(fù)用

定義一個Cache接口如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface Cache {
  /**
  * Refresh the cache. If succeed, return true, else return false;
  *
  * @return
  */
  boolean refresh();
 
  /**
  * How much time it will refresh the cache.
  *
  * @return
  */
  long interval();
}

但是這里碰到了問題,自己寫的Controller可以通過注入的方式輕而易舉的與Http服務(wù)跟Service層,數(shù)據(jù)庫層連接,但是如果CacheController實現(xiàn)Cache接口,會發(fā)現(xiàn)很難調(diào)用interval函數(shù)來找到間隔的時間。

因為CacheController也是一個Bean,需要通過Spring找到這個bean來調(diào)用。無法找到Bean,就不能調(diào)用Interval,也就不能夠順勢通過另外的線程來控制緩存刷新。為了獲取這個Bean可以將所有的CacheController都Autowired到一個CacheManagerController之中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Controller
public class CacheManagerController {
 
  @Autowired
  private CacheController cache;
 
  private static ScheduledExecutorService executor = Executors
     .newScheduledThreadPool(1);
 
  public CacheManagerController() {
   executor.scheduleAtFixedRate(() -> cache.refresh(), 0, cache.interval(),
      TimeUnit.MILLISECONDS);
  }
}

曾經(jīng)考慮這么做,但是發(fā)現(xiàn)一個問題,這樣做,CacheManagerController在初始化的時候,也就是構(gòu)造Bean的時候,各種的Cache還沒有被注入CacheController,而如果不將方法放入構(gòu)造函數(shù),那么CacheManagerController是無法自動的調(diào)用調(diào)度服務(wù)的。需要手動調(diào)用才行。但是程序的入口不一定從哪一個Controller進入,如果寫攔截器,也是很繁瑣,而且每次調(diào)用都會執(zhí)行。

這個時候,就通過一個CacheService來實現(xiàn)這個問題

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class CacheService {
  public static final long ONE_MINUTE = 60 * 1000;
 
  private static ScheduledExecutorService executor = Executors
     .newScheduledThreadPool(1);
 
  public static void register(Cache cache) {
   executor.scheduleAtFixedRate(() -> cache.refresh(), 0, cache.interval(),
      TimeUnit.MILLISECONDS);
  }
}
 
@Controller
public class CacheController implements Cache {
 
  // autowire 各種不同的service,或者是repo連接數(shù)據(jù)庫
  @Autowired
  private Service service;
 
  public CacheController() {
   CacheService.register(this);
  }
 
  // cache interface
  @Override
  public long interval() {
   return 1000;
  }
 
  @Override
  public boolean refresh() {
   return true;
  }
}

因為具體的CacheController是通過反射構(gòu)造成Bean由Spring管理的,所以可以直接通過無參構(gòu)造函數(shù)來注冊一下,這樣就沒有問題了,當Spring在加載CacheController的時候,就會直接調(diào)用CacheService的注冊方法,將緩存注冊到CacheService中定義的線程池當中,然后立刻執(zhí)行刷新方法,同時還會根據(jù)時間間隔來自動的刷新。

至于獲取指定的Cache,更簡單了,因為Cache本身是一個Controller,所以可以通過Autowire自動注冊到需要使用的其他Controller之中。

當然了,目前這么寫是沒有什么問題,但是當refresh為立刻調(diào)用的時候,會無法拿到Autowired注入的那些Service。因為Spring是統(tǒng)一全部實例化,然后再進行裝載的,所以,如果refresh函數(shù)中調(diào)用了service,那么顯然,程序肯定會報空指針異常的。這也是使用Controller來做Cache的問題。如果要獲得全部的Spring裝載的實例,那么肯定就都要修改構(gòu)造函數(shù)來將實例注入到統(tǒng)一的集合當中了,那樣就跟前文提到的問題一樣了,也就是獲取Bean。如果能夠獲取Bean,那直接就能調(diào)用實例方法,也就沒有這么多事情了。

總結(jié)

使用Controller的特點如下:

  • 代碼復(fù)用,定義的repo層,service層代碼都可以繼續(xù)使用,不用重寫
  • 因為Spring聲明周期的問題,refresh操作立刻執(zhí)行會拋異常,需要延時刷新

通過Listener來做

Listener有一個優(yōu)勢,就是可以通過一個寫一個PreloadListener 實現(xiàn)ServletContextListener,這樣就能夠利用Tomcat加載web.xml的時候,將代碼提前進行初始化了。

Listener的實現(xiàn)

?
1
2
3
4
5
6
7
8
9
10
11
public class PreloadListener implements ServletContextListener {
  @Override
  public void contextInitialized(ServletContextEvent servletContextEvent) {
   CacheFactory.init();
  }
 
  @Override
  public void contextDestroyed(ServletContextEvent servletContextEvent) {
 
  }
}

下面是web.xml的代碼

?
1
2
3
4
// web.xml
  <listener>
    <listener-class>com.sapphire.listener.PreloadListener</listener-class>
  </listener>

當然了,有優(yōu)勢肯定會存在劣勢,因為使用Listener的方式來提前加載,也會因為Web的聲明周期,產(chǎn)生問題。

Tomcat在加載Web.xml的時候,Listener的初始化,會在Spring容器啟動之前,這樣也就碰到一個問題。PreloadListener中可以調(diào)用的代碼,肯定是無法Autowire到任何的Bean的。這也就是對比Controller碰到的一個巨大的劣勢了,需要自己重寫那些Service。

除此以外, 還需要單獨寫一個Controller來刷新指定的緩存。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class CacheFactory {
  private static ConcurrentHashMap<String, Cache> caches = new ConcurrentHashMap<>();
  private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
 
  private static void register(Cache cache) {
   caches.put(cache.category(), cache);
  }
 
  private static void registerAll() {
   register(new StockCache());
  }
 
  public static void init() {
   registerAll();
 
   for (Cache cache : caches.values()) {
     executorService.scheduleAtFixedRate(new Runnable() {
      @Override
      public void run() {
        cache.refresh();
      }
     }, 0, cache.interval(), TimeUnit.MILLISECONDS);
   }
  }
 
  public static Cache getCache(String key) {
   if (caches.contains(key)) {
     return caches.get(key);
   }
   return null;
  }
}
 
// cache接口除了需要提供interval和refresh以外,還需要提供一個category來區(qū)分不同的Cache
public interface Cache {
  /**
  * Refresh the cache. If succeed, return true, else return false;
  *
  * @return
  */
  boolean refresh();
 
  /**
  * How much time it will refresh the cache.
  *
  * @return
  */
  long interval();
 
  /**
  * Cache's category. Each cache has distinct category.
  *
  * @return
  */
  String category();
}

這樣完成的CacheFactory,可以在PreloadListener之中調(diào)用init方法來初始化所有的Cache,來完成Cache的啟動。可以看出,所有的CacheFactory之中的方法都是靜態(tài)方法,可以直接由Controller層隨便調(diào)用。

之后,不同的Cache就需要單獨來寫init方法,放到各自實現(xiàn)的refresh方法之中。跟數(shù)據(jù)庫的鏈接等,都需要建立。不同的Cache都需要重寫各自的初始化方法,還需要寫一個讀取文件配置的東西讀取數(shù)據(jù)庫的一些配置信息。總之,感覺很麻煩。

總結(jié)

通過Listener來實現(xiàn),更加靈活,可以在容器啟動之前就將需要的信息加載到內(nèi)存之中,但是很多業(yè)務(wù)代碼都需要重新來寫,數(shù)據(jù)庫的鏈接,解析Property,靈活刷新的CacheController。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

原文鏈接:http://blog.csdn.net/ethanwhite/article/details/51278133

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 欧美一区免费 | 国产精品久久久久精 | 在线看一区 | 国产日韩一区 | 国产在线a | 懂色一区 | 色678黄网站全部免费 | 日韩欧美一区二区三区免费观看 | 精品国产91亚洲一区二区三区www | 人妖天堂狠狠ts人妖天堂狠狠 | 国产精品永久 | 婷婷在线视频 | 久久一级 | 精品免费 | 在线播放一级片 | 亚洲青涩在线 | 国产精品成人国产乱一区 | 欧美日本精品 | 国产日韩一区二区三区 | 午夜成人免费电影 | 欧美日韩一区二区三区不卡视频 | 国产www视频| 26uuu国产电影一区二区 | 日韩视频精品 | 亚洲国产中文字幕在线 | 欧美一区二区免费 | 在线日本视频 | 黄色影院在线观看 | 日本一级毛片免费看 | 久久综合区 | 日日操综合 | 一本大道专区 | 日产精品一区二区三区在线观看 | 日本特黄特色aaa大片免费 | 二区视频 | 日韩欧美在线不卡 | 亚洲精品区 | 亚洲无线看 | 午夜爽视频 | 久草热8精品视频在线观看 毛片黄片免费观看 | 色婷婷综合久久久中字幕精品久久 |