日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

装饰者模式源码解析(spring-session mybatis jdk servlet)

發布時間:2024/4/13 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 装饰者模式源码解析(spring-session mybatis jdk servlet) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
那在JDK中體現最明顯的,就是JAVA IO方面的一些類,那在JAVA IO中,我們為了增加緩存,我們使用BufferedReader,那現在我們來看一下,那因為增加緩存的功能,類有很多,子類也就需要很多,那現在我們看一下,BufferedReaderpublic class BufferedReader extends Reader看一下,他首先繼承了Reader,進來public abstract class Reader implements Readable, Closeable是一個抽象類,接著回來,然后BufferedReader把Reader放到自己的類中,是inprivate Reader in;public BufferedReader(Reader in, int sz) {super(in);if (sz <= 0)throw new IllegalArgumentException("Buffer size <= 0");this.in = in;cb = new char[sz];nextChar = nChars = 0; }通過Reader來構造BufferedReader,現在我們來類比一下,抽象的煎餅,抽象的裝飾者,構造的時候,用抽象的煎餅來構造他,和這里是一致的,正因為在JDK中的JAVA IO,采用了裝飾者模式,我們可以無限次的進行裝飾轉換,轉換的目標啊,就是為了得到我們想要的數據類型流對象,class BufferedInputStream extends FilterInputStream 同理BufferedInputStream也是一樣的,class BufferedOutputStream extends FilterOutputStream這兩個類我們只做一個,首先它繼承FilterInputStream,而FilterInputStream又繼承FilterInputStream,class FilterInputStream extends InputStream那InputStream是一個抽象類,public abstract class InputStream implements Closeable接著回來,看一下BufferedInputStream他的構造器,這里有兩個,隨便看一個就可以,public BufferedInputStream(InputStream in) {this(in, DEFAULT_BUFFER_SIZE); }public BufferedInputStream(InputStream in, int size) {super(in);if (size <= 0) {throw new IllegalArgumentException("Buffer size <= 0");}buf = new byte[size]; }傳入的InputStream,是BufferedInputStream父類的父類,我們看一下fill這個方法,在這個fill這個方法中,private void fill() throws IOException {byte[] buffer = getBufIfOpen();if (markpos < 0)pos = 0; /* no mark: throw away the buffer */else if (pos >= buffer.length) /* no room left in buffer */if (markpos > 0) { /* can throw away early part of the buffer */int sz = pos - markpos;System.arraycopy(buffer, markpos, buffer, 0, sz);pos = sz;markpos = 0;} else if (buffer.length >= marklimit) {markpos = -1; /* buffer got too big, invalidate mark */pos = 0; /* drop buffer contents */} else if (buffer.length >= MAX_BUFFER_SIZE) {throw new OutOfMemoryError("Required array size too large");} else { /* grow buffer */int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?pos * 2 : MAX_BUFFER_SIZE;if (nsz > marklimit)nsz = marklimit;byte nbuf[] = new byte[nsz];System.arraycopy(buffer, 0, nbuf, 0, pos);if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {// Can't replace buf if there was an async close.// Note: This would need to be changed if fill()// is ever made accessible to multiple threads.// But for now, the only way CAS can fail is via close.// assert buf == null;throw new IOException("Stream closed");}buffer = nbuf;}count = pos;int n = getInIfOpen().read(buffer, pos, buffer.length - pos);if (n > 0)count = n + pos; }就實現讀取流數據,我們再 看一下FileInputStreamclass FilterInputStream extends InputStream那這里的方法相對簡單一些,我們看幾個關鍵的,首先是構造器,傳入File,然后裝飾成FileInputStream,public FileInputStream(File file) throws FileNotFoundException {String name = (file != null ? file.getPath() : null);SecurityManager security = System.getSecurityManager();if (security != null) {security.checkRead(name);}if (name == null) {throw new NullPointerException();}if (file.isInvalid()) {throw new FileNotFoundException("Invalid file path");}fd = new FileDescriptor();fd.attach(this);path = name;open(name); }那FileInputStream的父類,我們看一下,InputStream是抽象類,我們現在來看一下他的UML,他有很多子類,這里面有超多的子類,我們看一下FilterInputStream,再打開幾個實現,為了更好地對比,這里面打開三個,然后我們看一下FilterInputStream他的子類也有很多,例如剛剛講的BufferedInputStream,還有DataInputStream,還有很多,比如LineInputStream,那我們可以看到在裝飾者模式中,我們的類是非常的多,但是FilterInputStream,是一個裝飾者下面都是實際的裝飾者,還有一些類我們就不顯示到這里了,那Reader和Writer流中

也是一樣的,大同小異,我們在使用IO流的時候,因為類的數量比較多,有時候我們也記不住,但是如果我們能夠識別出,哪些是抽象被裝飾,哪些是實際被裝飾者,哪些是抽象裝飾者,哪些是實體裝飾者,那其實對我們理解來說是非常有益處的,那這些就是裝飾者模式在JDK中的應用,那Spring中,你再看一個類,TransactionAwareCacheDecorator,聰明的可以看出來,這個類是處理Spring緩存和同步事務的相關類,那從類里面我們可以看出來,它實現了一個Cache

又組合到這里,我們是不是可以認為他是一個Cache的裝飾者,因為這個類名也是非常的明顯,然后他的構造器也是非常的明顯,把Cache放到入參里面,Spring這個類的主要目的是提供緩存,和Spring事務的同步級別,感興趣的可以看一下,在Servlet中也大量的使用了裝飾者模式,包括我們所講的單點登錄,也對Servlet進行了包裝,我們講過有這么一個類,private final class SessionRepositoryRequestWrapperprivate final class SessionRepositoryRequestWrapperextends HttpServletRequestWrapper {// HttpServletResponse 實例private final HttpServletResponse response;// ServletContext 實例private final ServletContext servletContext;// requestedSession session對象private S requestedSession; // 是否緩存 sessionprivate boolean requestedSessionCached;// sessionIdprivate String requestedSessionId;// sessionId 是否有效private Boolean requestedSessionIdValid;// sessionId 是否失效private boolean requestedSessionInvalidated;// 省略方法 }裝飾者模式在Spring Session和Servlet中的使用,首先這個類繼承了HttpServletRequestWrapper,我們看一下HttpServletRequestWrapper這個類是Servlet里面的類,Session是Spring Session包下的類,他繼承了這個類,然后在構建他自己的時候呢,又把HttpServletRequest傳入進來,private SessionRepositoryRequestWrapper(HttpServletRequest request,HttpServletResponse response, ServletContext servletContext) {super(request);this.response = response;this.servletContext = servletContext; }那他繼承了Wrapper,傳入的又是ServletRequest,那他兩是什么關系呢,public class HttpServletRequestWrapper extends ServletRequestWrapper implementsHttpServletRequestHttpServletRequestWrapper繼承ServletRequestWrapper并且實現了HttpServletRequest,這樣就很好理解了,也就是說我們繼承的HttpServletRequestWrapper這個類,也就實現了HttpServletRequest接口,那在構建他的時候,我們就可以把被裝飾的對象,傳入進來,然后生成我們自己包裝好的類,這里可以看出來,HttpServletRequestWrapper他包裝了HttpServletRequest,而SessionRepositoryRequestWrapper呢,又借力打力,他又借著HttpServletRequestWrapper繼續包裝,我們再看一下HttpServletRequestWrapper這個類,在構造的時候,也是同樣的,把要實現的,要裝飾的,作為構造的一個入參,同時我們再看一下,在這個類中getSession,我們看一下這個方法,我們可以看到明顯是override,明顯是覆蓋了這個方法,包括獲取Servlet上下文,也同理獲取getRequestedSessionId,這個HttpServletRequestWrapper實現了HttpServletRequest接口,而HttpServletRequest又繼承了SevletRequest接口,繼續往上看,SevletRequest他目前是最頂級的,那我們看一下ServletRequest,在他這個層次呢,有沒有自己的呢public class ServletRequestWrapper implements ServletRequestServletRequestWrapper他本身也存在自己的Wrapper包裝器,注意這里的Requestprivate ServletRequest request;正是父類ServletRequest實現的這個類,構造的時候也是同理public ServletRequestWrapper(ServletRequest request) {if (request == null) {throw new IllegalArgumentException("Request cannot be null");}this.request = request; }我們看一下UML,因為這里面有很多,包裝類和非包裝類,我們隨便打開幾個來看一下,他們的結構,一直到Spring Session的使用當中,首先HttpServletRequest跑不掉,他呢作為一個接口,繼承了ServletRequest接口,我們再看一下他下面的HttpServletRequestWrapper,現在還在Servlet中,同時ServletRequest他下面的實現還有一個ServletRequestWrapper,ServletRequestWrapper這里是一個類,HttpServletRequestWrapper這個是一個接口,在這個接口下邊繼續包裝,那繼續來看,SessionRepositoryRequestWrapper,這些都是裝飾者的使用

因為這里屬性比較多,如果打開的話,這個圖就不容易看了,我們剛剛在類中所講的委托對象,記住就可以了,那這里面用的也是通過委托的方式,那這條線是指Request這條線,那在Response中,是一樣的,這里說一下,因為裝飾者模式,和適配器模式,都可以成為包裝器,所以結尾都可能是Wrapper,但是具體的是適配器模式,還是裝飾者模式呢,我們還是要看類里面的實現,以及類與類之間的結構,所以我們不能因為是Wrapper就認為是裝飾者模式,或者看到Wrapper就是適配器模式,有些地方就把這兩個叫做包裝模式,或者稱Wrapper這個類為包裝器,那具體用什么模式呢,我們還要具體看,那在Mybatis當中,是怎么使用裝飾者模式的呢,我們看一下Mybatis中Cache這個類,叫這個類名的特別多,我們直接寫一下包名,org.apache.ibatis.cache.Cache,我們找到ibatis.cache這個包下的Cache這個類,可以看到這個就是一個接口public interface Cache {String getId();int getSize();void putObject(Object key, Object value);Object getObject(Object key);Object removeObject(Object key);void clear();ReadWriteLock getReadWriteLock();}同時這里有getId,getSize,讀寫鎖,獲取他的size,我們看一下這個包在哪里,我們可以看一下他的包叫decorators,更明顯了,這些類都是用來裝飾Cache的,我們隨便看一個,FifoCache先進先出算法package org.apache.ibatis.cache.decorators;public class FifoCache implements Cache 他呢實現Cache這個類,里面看他的命名delegateprivate final Cache delegate;private final LinkedList<Object> keyList;private int size;public FifoCache(Cache delegate) {this.delegate = delegate;this.keyList = new LinkedList<Object>();this.size = 1024;}他這個命名還是非常好的,也就是先進先出這個Cache呢,都是委托給Cache來做的,不過在里面加了自己的實現,比如說這里面的keyList,使用的是LinkedList,同時new一個LinkedList,LinkedList是一個雙端隊列,還有LruCache,這個你們會比較熟悉/** Lru (first in, first out) cache decorator*/ public class LruCache implements Cache 最近最少使用的裝飾者,這個注釋寫的很明顯,而且我在看這段源碼的時候,我發現這里面對象的命名,相對容易理解一些,并且注釋非常精簡,這個也是值得我們學習的地方,那從名字我們來看一下,ScheduledCache這個肯定是調度緩存方面的,SerializedCache還有序列號和反序列化的一些緩存,軟引用SoftCache,還有同步緩存SynchronizedCache,還有多線程并發訪問,這里可以看一下,里面的方法都是有同步方法修飾的,public class SynchronizedCache implements Cache {private Cache delegate;public SynchronizedCache(Cache delegate) {this.delegate = delegate;}public String getId() {return delegate.getId();}public int getSize() {acquireReadLock();try {return delegate.getSize();} finally {releaseReadLock();}}public void putObject(Object key, Object object) {acquireWriteLock();try {delegate.putObject(key, object);} finally {releaseWriteLock();}}public Object getObject(Object key) {acquireReadLock();try {return delegate.getObject(key);} finally {releaseReadLock();}}public Object removeObject(Object key) {acquireWriteLock();try {return delegate.removeObject(key);} finally {releaseWriteLock();}}public void clear() {acquireWriteLock();try {delegate.clear();} finally {releaseWriteLock();}}public ReadWriteLock getReadWriteLock() {return delegate.getReadWriteLock();}public int hashCode() {return delegate.hashCode();}public boolean equals(Object obj) {return delegate.equals(obj);}private void acquireReadLock() {getReadWriteLock().readLock().lock();}private void releaseReadLock() {getReadWriteLock().readLock().unlock();}private void acquireWriteLock() {getReadWriteLock().writeLock().lock();}private void releaseWriteLock() {getReadWriteLock().writeLock().unlock();}}那這個就更好理解,他只是說,在Cache上一層包裝了一下,并且都加了方法,還有一個關于事務的一個Cachepublic class TransactionalCache implements Cache事務性的一個緩存,那有興趣的非常建議,把Mybatis Cache這些類的源碼看一遍,這些都是對Cache的一些裝飾,剛剛一起看了JDK的源碼,TOMCAT,SpringSession中的,還有Mybatis中的,關于裝飾者模式的一個使用,那裝飾者模式在源碼框架中,應用的如此廣泛,包括我們使用的JDK,所以裝飾者模式是我們非常值得學習的一個設計模式,希望你們呢能夠理解透,鞏固好,同時呢,觸類旁通,在我們自己的業務中,來抽象出來可以使用裝飾者模式的一些業務模型,當然我們不是為了使用設計模式而使用設計模式,一定是使用對應場景的時候,才來使用他

?

總結

以上是生活随笔為你收集整理的装饰者模式源码解析(spring-session mybatis jdk servlet)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。