設計模式是解決問題的方案,從大神的代碼中學習對設計模式的使用,可以有效提升個人編碼及設計代碼的能力。本系列博文用於總結閱讀過的框架源碼(Spring系列、Mybatis)及JDK源碼中 所使用過的設計模式,並結合個人工作經驗,重新理解設計模式。
本篇博文主要看一下行爲型的幾個設計模式,即,策略模式、模板方法模式、迭代器模式、觀察者模式 及 責任鏈模式。
策略模式
個人理解
去年看了蠻多源碼,發現 框架的開發者在實際使用設計模式時,大都會根據實際情況 使用其變體,老老實實按照書上的類圖及定義去設計代碼的比較少。不過我們依然還是先看一下書上的定義,然後比較一下理論與實踐的一些差別吧。策略模式的類圖及定義如下。
定義一系列算法,封裝每個算法 並使它們可以互換。該模式的主要角色如下:
- Strategy接口:用於定義一個算法族,它們都具有behavior()方法;
- Context:使用該算法的類,持有Strategy對象,其中的setStrategy(Strategy stra)方法可以動態地改變strategy對象,以此改變自己所使用的算法。
很多書上都使用Duck和QuackBehavior作爲示例進行說明,這裏就不重複咯,主要看一下Spring中是如何使用該模式的。
Spring中的實現
Spring的 AbstractAutowireCapableBeanFactory 在進行bean實例化時使用了策略模式的變種,其中InstantiationStrategy 接口 定義了實例化方法,實現類SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy 分別實現了各自的算法,AbstractAutowireCapableBeanFactory 則通過持有 InstantiationStrategy 對象,對算進行使用。其源碼實現如下。
/**
* 本接口用於定義bean實例的創建,通過給定的RootBeanDefinition對象
* 本組件使用了策略模式,因爲各種情況,需要使用不同的方法來實現,包括使用CGLIB動態創建子類
* @author Rod Johnson
* @since 1.1
*/
public interface InstantiationStrategy {
/**
* 返回一個bean實例,使用BeanFactory給定的參數
*/
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner)
throws BeansException;
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
Constructor<?> ctor, Object[] args) throws BeansException;
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
Object factoryBean, Method factoryMethod, Object[] args) throws BeansException;
}
public class SimpleInstantiationStrategy implements InstantiationStrategy {
/**
* 具體使用哪個策略進行bean的實例化,是在這個實現類中決定的
*/
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
// 如果beanDefinition中沒有方法覆蓋,則使用Java的反射機制實例化對象,否則使用CGLIB策略
if (beanDefinition.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (beanDefinition.constructorArgumentLock) {
// 獲取對象的構造方法或生成對象的工廠方法對bean進行實例化
constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
// 如果前面沒有獲取到構造方法,則通過反射獲取
if (constructorToUse == null) {
// 使用JDK的反射機制,判斷要實例化的Bean是否是接口
final Class clazz = beanDefinition.getBeanClass();
// 如果clazz是一個接口,直接拋出異常
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
// 這裏是一個匿名內置類,使用反射機制獲取Bean的構造方法
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {
public Constructor run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 使用BeanUtils實例化,通過反射機制調用”構造方法.newInstance(arg)”來進行實例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
/**
* !!!!!!!!!!!!!!
* 使用CGLIB來實例化對象
* 調用了其子類CglibSubclassingInstantiationStrategy中的實現
* !!!!!!!!!!!!!!
*/
return instantiateWithMethodInjection(beanDefinition, beanName, owner);
}
}
}
public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {
/**
* 下面兩個方法都通過實例化自己的私有靜態內部類CglibSubclassCreator,
* 然後調用該內部類對象的實例化方法instantiate()完成實例化
*/
protected Object instantiateWithMethodInjection(
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
// 必須生成cglib子類
return new CglibSubclassCreator(beanDefinition, owner).instantiate(null, null);
}
@Override
protected Object instantiateWithMethodInjection(
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
Constructor ctor, Object[] args) {
return new CglibSubclassCreator(beanDefinition, owner).instantiate(ctor, args);
}
/**
* 爲避免3.2之前的Spring版本中的外部cglib依賴而創建的內部類
*/
private static class CglibSubclassCreator {
private final RootBeanDefinition beanDefinition;
private final BeanFactory owner;
public CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
}
//使用CGLIB進行Bean對象實例化
public Object instantiate(Constructor ctor, Object[] args) {
//實例化Enhancer對象,併爲Enhancer對象設置父類,生成Java對象的參數,比如:基類、回調方法等
Enhancer enhancer = new Enhancer();
//將Bean本身作爲其父類
enhancer.setSuperclass(this.beanDefinition.getBeanClass());
enhancer.setCallbackFilter(new CallbackFilterImpl());
enhancer.setCallbacks(new Callback[] {
NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(),
new ReplaceOverrideMethodInterceptor()
});
//使用CGLIB的create方法生成實例對象
return (ctor == null) ? enhancer.create() : enhancer.create(ctor.getParameterTypes(), args);
}
}
}
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/** 創建bean實例的策略,注意 這裏直接實例化的是 CglibSubclassingInstantiationStrategy 對象 */
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
/**
* 設置用於創建bean實例的實例化策略,默認使用CglibSubclassingInstantiationStrategy
*/
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
protected InstantiationStrategy getInstantiationStrategy() {
return this.instantiationStrategy;
}
/**
* 使用默認的無參構造方法實例化Bean對象
*/
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
// 獲取系統的安全管理接口,JDK標準的安全管理API
if (System.getSecurityManager() != null) {
// 這裏是一個匿名內置類,根據實例化策略創建實例對象
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
/**
* !!!!!!!!!!!!!!
* 使用初始化策略實例化Bean對象
* !!!!!!!!!!!!!!
*/
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
...
}
與標準的策略模式的設計區別在於,實現類CglibSubclassingInstantiationStrategy並不是直接實現了InstantiationStrategy接口,而是繼承了SimpleInstantiationStrategy,SimpleInstantiationStrategy直接實現了 通過JDK反射機制實例化bean的策略,而CglibSubclassingInstantiationStrategy則是在自己的私有靜態內部類中 完成的 通過CGLIB實例化bean的策略。
另外,雖然AbstractAutowireCapableBeanFactory默認持有的是CglibSubclassingInstantiationStrategy的實例,但具體使用哪個實現類中的策略,則是由CglibSubclassingInstantiationStrategy的父類SimpleInstantiationStrategy中的instantiate()方法決定的。也就是說,雖然持有的是CglibSubclassingInstantiationStrategy對象,但實際上可能使用的是 JDK反射機制實例化bean的策略。
設計模式的生產實踐可能比 理論上的那些示例複雜的多,所以,若想確實提高自己代碼的設計能力,還是要擺脫書本,多看實際應用。
Mybatis 中的實現
mybatis 的 DefaultSqlSession 使用了策略模式,DefaultSqlSession 扮演了 Context 的角色,Executor 接口及其實現類扮演了策略接口及實現。DefaultSqlSession 持有 Executor 對象,在DefaultSqlSession 實例化時通過構造方法傳入具體的 Executor 對象,根據持有的 Executor 對象的不同,而使用不同的策略進行數據庫操作。具體使用哪個 Executor 的實例,由 Configuration 的 newExecutor() 方法決定。
public class DefaultSqlSession implements SqlSession {
private final Executor executor;
/**
* 在構造方法中爲 executor 賦值,沒有提供專門的set方法
*/
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
/**
* executor的不同,決定了DefaultSqlSession使用哪種策略執行SQL操作
*/
@Override
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
executor.query(ms, wrapCollection(parameter), rowBounds, handler);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
@Override
public int update(String statement, Object parameter) {
try {
dirty = true;
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
}
public interface Executor {
int update(MappedStatement ms, Object parameter) throws SQLException;
<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
void commit(boolean required) throws SQLException;
void rollback(boolean required) throws SQLException;
Transaction getTransaction();
......
}
public abstract class BaseExecutor implements Executor {
......
protected BaseExecutor(Configuration configuration, Transaction transaction) {
this.transaction = transaction;
this.deferredLoads = new ConcurrentLinkedQueue<>();
this.localCache = new PerpetualCache("LocalCache");
this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
this.closed = false;
this.configuration = configuration;
this.wrapper = this;
}
......
}
public class SimpleExecutor extends BaseExecutor {
public SimpleExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
}
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
// 獲取配置對象
Configuration configuration = ms.getConfiguration();
// 創建 StatementHandler 對象,實際返回的是 RoutingStatementHandler 對象,前面介紹過,
// 其中根據 MappedStatement.statementType 選擇具體的 StatementHandler 實現
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// 完成 Statement 的創建和初始化,該方法首先會調用 StatementHandler.prepare() 方法
// 創建 Statement 對象, 然後調用 StatementHandler. parameterize() 方法處理佔位符
stmt = prepareStatement(handler, ms.getStatementLog());
// 調用 StatementHandler.query() 方法,執行 SQL 語句,並通過 ResultSetHandler 完成
// 結果集的映射
return handler.query(stmt, resultHandler);
} finally {
// 關閉 Statement 對象
closeStatement(stmt);
}
}
......
}
public class BatchExecutor extends BaseExecutor {
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
// 獲取配置對象
final Configuration configuration = ms.getConfiguration();
// 創建 StatementHandler 對象
final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
final BoundSql boundSql = handler.getBoundSql();
// 獲取 SQL 語句
final String sql = boundSql.getSql();
final Statement stmt;
// 如果當前執行的 SQL 模式與上次執行的 SQL 模式相同且對應的 MappedStatement 對象相同
if (sql.equals(currentSql) && ms.equals(currentStatement)) {
// 獲取 statementList 集合中最後一個 Statement 對象
int last = statementList.size() - 1;
stmt = statementList.get(last);
applyTransactionTimeout(stmt);
// 綁定實參,處理佔位符 “?”
handler.parameterize(stmt);//fix Issues 322
// 查找對應的 BatchResult 對象,並記錄用戶傳入的實參
BatchResult batchResult = batchResultList.get(last);
batchResult.addParameterObject(parameterObject);
} else {
Connection connection = getConnection(ms.getStatementLog());
// 創建新的 Statement 對象
stmt = handler.prepare(connection, transaction.getTimeout());
// 綁定實參,處理佔位符“?”
handler.parameterize(stmt); //fix Issues 322
// 更新 currentSql 和 currentStatement
currentSql = sql;
currentStatement = ms;
// 將新創建的 Statement 對象添加到 statementList 集合中
statementList.add(stmt);
// 添加新的 BatchResult 對象
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
// 底層通過調用 Statement.addBatch() 方法添加 SQL 語句
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
......
}
public class Configuration {
/**
* 在這個方法中決定使用哪個 Executor 實現
*/
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
......
}
模板方法模式
個人理解
在該模式中,一個算法可以分爲多個步驟,這些步驟的執行次序在一個被稱爲“模板方法”的方法中定義,而算法的每個步驟都對應着一個方法,這些方法被稱爲 “基本方法”。 模板方法按照它定義的順序依次調用多個基本方法,從而實現整個算法流程。在模板方法模式中,會將模板方法的實現以及那些固定不變的基本方法的實現放在父類中,而那些不固定的基 本方法在父類中只是抽象方法,其真正的實現代碼會被延遲到子類中完成。
我覺得這是最簡單且常用的設計模式之一咯,自己在實現一些功能時也會使用這種模式,在抽象類中定義好流程的執行順序,通用的流程在抽象類中實現,個性化的流程交給各個子類去實現。spring及mybatis中均有應用。
Spring中的應用
Spring 中的 AbstractApplicationContext 和其子類 AbstractRefreshableApplicationContext、GenericApplicationContext 使用了模板方法模式。源碼實現及詳細註釋如下。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
/**
* 告訴子類啓動refreshBeanFactory()方法,BeanDefinition資源文件的載入
* 從子類的refreshBeanFactory()方法啓動開始
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 這裏使用了模板方法模式,自己定義了流程,個性化的方法實現交由子類完成
// 其中,refreshBeanFactory() 和 getBeanFactory()爲抽象方法
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
/**
* 在這裏完成了容器的初始化,並賦值給自己private的beanFactory屬性,爲下一步調用做準備
* 從父類AbstractApplicationContext繼承的抽象方法,自己做了實現
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果已經建立了IoC容器,則銷燬並關閉容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 創建IoC容器,DefaultListableBeanFactory類實現了ConfigurableListableBeanFactory接口
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 定製化IoC容器,如設置啓動參數,開啓註解的自動裝配等
customizeBeanFactory(beanFactory);
// 載入BeanDefinition,這裏又使用了一個委派模式,在當前類定義此抽象方法,子類容器具體實現
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 給自己的屬性賦值
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}
}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
if (this.refreshed) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
this.refreshed = true;
}
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
}
Mybatis中的應用
mybatis的 Executor 組件使用了該模式,其中抽象類 BaseExecutor 定義了模板方法和抽象方法,實現類 SimpleExecutor、BatchExecutor 及 ReuseExecutor 對抽象方法進行具體實現。源碼如下。
public abstract class BaseExecutor implements Executor {
@Override
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
// 判斷當前 Executor 是否已經關閉
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// clearLocalCache() 方法中會調用 localCache()、localOutputParameterCache() 兩個
// 緩存的 clear() 方法完成清理工作。這是影響一級緩存中數據存活時長的第三個方面
clearLocalCache();
// 調用 doUpdate() 抽象方法執行 SQL 語句
return doUpdate(ms, parameter);
}
public List<BatchResult> flushStatements(boolean isRollBack) throws SQLException {
// 判斷當前 Executor 是否已經關閉
if (closed) {
throw new ExecutorException("Executor was closed.");
}
// 調用抽象方法 doFlushStatements(),其參數 isRollBack 表示是否執行 Executor 中緩存的
// SQL 語句,false 表示執行,true 表示不執行
return doFlushStatements(isRollBack);
}
/**
* 調用 doQuery() 方法完成數據庫查詢,並得到映射後的結果集對象,
*/
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
// 在緩存中添加佔位符
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
// 調用 doQuery() 抽象方法,完成數據庫查詢操作,並返回結果集對象
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
// 刪除佔位符
localCache.removeObject(key);
}
// 將真正的結采對象添加到一級緩存中
localCache.putObject(key, list);
// 是否爲存儲過程調用
if (ms.getStatementType() == StatementType.CALLABLE) {
// 緩存輸出類型的參數
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
@Override
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameter);
return doQueryCursor(ms, parameter, rowBounds, boundSql);
}
protected abstract int doUpdate(MappedStatement ms, Object parameter)
throws SQLException;
protected abstract List<BatchResult> doFlushStatements(boolean isRollback)
throws SQLException;
protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
throws SQLException;
protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)
throws SQLException;
}
public class SimpleExecutor extends BaseExecutor {
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
// 獲取配置對象
Configuration configuration = ms.getConfiguration();
// 創建 StatementHandler 對象,實際返回的是 RoutingStatementHandler 對象,前面介紹過,
// 其中根據 MappedStatement.statementType 選擇具體的 StatementHandler 實現
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// 完成 Statement 的創建和初始化,該方法首先會調用 StatementHandler.prepare() 方法
// 創建 Statement 對象, 然後調用 StatementHandler. parameterize() 方法處理佔位符
stmt = prepareStatement(handler, ms.getStatementLog());
// 調用 StatementHandler.query() 方法,執行 SQL 語句,並通過 ResultSetHandler 完成
// 結果集的映射
return handler.query(stmt, resultHandler);
} finally {
// 關閉 Statement 對象
closeStatement(stmt);
}
}
@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
Cursor<E> cursor = handler.queryCursor(stmt);
stmt.closeOnCompletion();
return cursor;
}
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) {
return Collections.emptyList();
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return stmt;
}
}
public class BatchExecutor extends BaseExecutor {
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
// 獲取配置對象
final Configuration configuration = ms.getConfiguration();
// 創建 StatementHandler 對象
final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
final BoundSql boundSql = handler.getBoundSql();
// 獲取 SQL 語句
final String sql = boundSql.getSql();
final Statement stmt;
// 如果當前執行的 SQL 模式與上次執行的 SQL 模式相同且對應的 MappedStatement 對象相同
if (sql.equals(currentSql) && ms.equals(currentStatement)) {
// 獲取 statementList 集合中最後一個 Statement 對象
int last = statementList.size() - 1;
stmt = statementList.get(last);
applyTransactionTimeout(stmt);
// 綁定實參,處理佔位符 “?”
handler.parameterize(stmt);//fix Issues 322
// 查找對應的 BatchResult 對象,並記錄用戶傳入的實參
BatchResult batchResult = batchResultList.get(last);
batchResult.addParameterObject(parameterObject);
} else {
Connection connection = getConnection(ms.getStatementLog());
// 創建新的 Statement 對象
stmt = handler.prepare(connection, transaction.getTimeout());
// 綁定實參,處理佔位符“?”
handler.parameterize(stmt); //fix Issues 322
// 更新 currentSql 和 currentStatement
currentSql = sql;
currentStatement = ms;
// 將新創建的 Statement 對象添加到 statementList 集合中
statementList.add(stmt);
// 添加新的 BatchResult 對象
batchResultList.add(new BatchResult(ms, sql, parameterObject));
}
// 底層通過調用 Statement.addBatch() 方法添加 SQL 語句
handler.batch(stmt);
return BATCH_UPDATE_RETURN_VALUE;
}
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
throws SQLException {
Statement stmt = null;
try {
flushStatements();
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql);
Connection connection = getConnection(ms.getStatementLog());
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
flushStatements();
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Connection connection = getConnection(ms.getStatementLog());
Statement stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
Cursor<E> cursor = handler.queryCursor(stmt);
stmt.closeOnCompletion();
return cursor;
}
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
try {
// results 集合用於儲存批處理的結采
List<BatchResult> results = new ArrayList<>();
// 如果明確指定了要回滾事務,則直接返回空集合,忽略 statementList 集合中記錄的 SQL 語句
if (isRollback) {
return Collections.emptyList();
}
// 遍歷 statementList 集合
for (int i = 0, n = statementList.size(); i < n; i++) {
// 獲取 Statement 對象
Statement stmt = statementList.get(i);
applyTransactionTimeout(stmt);
// 獲取對應 BatchResult 對象
BatchResult batchResult = batchResultList.get(i);
try {
// 調用 Statement.executeBatch() 方法批量執行其中記錄的 SQL 語句,並使用返回的 int 數組
// 更新 BatchResult.updateCounts 字段,其中每一個元素都表示一條 SQL 語句影響的記錄條數
batchResult.setUpdateCounts(stmt.executeBatch());
MappedStatement ms = batchResult.getMappedStatement();
List<Object> parameterObjects = batchResult.getParameterObjects();
// 獲取配置的 KeyGenerator 對象
KeyGenerator keyGenerator = ms.getKeyGenerator();
if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {
Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;
// 獲取數據庫生成的主鍵,並設置到 parameterObjects 中,前面已經分析過,這裏不再重複
jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);
} else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141
// 對於其他類型的 KeyGenerator,會調用其 processAfter() 方法
for (Object parameter : parameterObjects) {
keyGenerator.processAfter(this, ms, stmt, parameter);
}
}
// Close statement to close cursor #1109
closeStatement(stmt);
} catch (BatchUpdateException e) {
StringBuilder message = new StringBuilder();
message.append(batchResult.getMappedStatement().getId())
.append(" (batch index #")
.append(i + 1)
.append(")")
.append(" failed.");
if (i > 0) {
message.append(" ")
.append(i)
.append(" prior sub executor(s) completed successfully, but will be rolled back.");
}
throw new BatchExecutorException(message.toString(), e, results, batchResult);
}
// 添加 BatchResult 到 results 集合
results.add(batchResult);
}
return results;
} finally {
// 關閉所有 Statement 對象,並清空 currentSql 字段、清空 statementList 集合、
// 清空 batchResultList 集合(略)
for (Statement stmt : statementList) {
closeStatement(stmt);
}
currentSql = null;
statementList.clear();
batchResultList.clear();
}
}
}
public class ReuseExecutor extends BaseExecutor {
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
}
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
}
@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
return handler.queryCursor(stmt);
}
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) {
for (Statement stmt : statementMap.values()) {
closeStatement(stmt);
}
statementMap.clear();
return Collections.emptyList();
}
}
可以看得出來,模板方法就是BaseExecutor的update()、flushStatements()、queryFromDatabase() 及 queryCursor(),分別使用了抽象方法doUpdate()、doFlushStatements()、doQuery() 及 doQueryCursor()。
迭代器模式
個人理解
這個模式最經典的實現莫過於 Java的集合類咯。同樣還是先簡單介紹一下這個設計模式,然後結合ArrayList的源碼進行分析。
本設計模式用於提供一種遍歷集合元素的方法,且不暴露集合對象的內部表示。其主要角色 和 簡單實現如下:
- Aggregate:聚合類,有一個可以獲取 Iterator 對象的 iterator() 方法;
- Iterator:主要定義了hasNest() 和 next()方法;
public interface Aggregate {
Iterator iterator();
}
public class ConcreteAggregate implements Aggregate {
private Integer[] elements;
public ConcreteAggregate() {
elements = new Integer[10];
for (int i = 0; i < elements.length; i++) {
elements[i] = i;
}
}
@Override
public Iterator iterator() {
return new ConcreteIterator(elements);
}
}
public interface Iterator<Integer> {
boolean hasNext();
Integer next();
}
public class ConcreteIterator<Integer> implements Iterator {
private Integer[] elements;
private int position = 0;
public ConcreteIterator(Integer[] elements) {
this.elements = elements;
}
@Override
public boolean hasNext() {
return position < elements.length;
}
@Override
public Integer next() {
return elements[position ++];
}
}
public class Client {
public static void main(String[] args) {
Aggregate aggregate = new ConcreteAggregate();
Iterator<Integer> iterator = aggregate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
ArrayList 對迭代器模式的實現
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
/**
* 存儲ArrayList元素的數組緩衝區。ArrayList的容量是此數組緩衝區的長度
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* ArrayList的大小(其包含的元素數)
*/
private int size;
/**
* 以正確的順序返回此列表中元素的迭代器
*/
public Iterator<E> iterator() {
return new Itr();
}
/**
* ArrayList的私有內部類,其實現了Iterator接口,所以也是一個迭代器
* AbstractList.Itr的優化版本
*/
private class Itr implements Iterator<E> {
int cursor; // 要返回的下一個元素的索引
int lastRet = -1; // 返回的最後一個元素的索引;如果沒有則返回 -1
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
}
}
觀察者模式
個人理解
這個模式也是平時很少使用的,所以就簡單介紹一下,然後結合JDK中的源碼加深理解。該模式用於定義對象之間的一對多依賴,當一個對象狀態改變時,它的所有依賴都會收到通知,然後自動更新。類圖和主要角色如下:
- Subject主題:具有註冊、移除及通知觀察者的功能,主題是通過維護一個觀察者列表來實現這些功能的;
- Observer觀察者:其註冊需要Subject的registerObserver()方法。
JDK中的源碼實現
java.util包中提供了 Observable 類和 Observer 接口,其中要求,被觀察者需要繼承Observable類,觀察則需要實現Observer接口。下面看一下其源碼實現。
/**
* 當一個類希望獲知 所觀察的對象的變化時,可以通過實現本接口來完成
* 而被觀察的對象則需要繼承 Observable 類
* @author Chris Warth
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
* 每當所觀察的對象發生更改時,此方法都會被調用。應用程序調用Observable對象的
* notifyObservators()方法時,將通知所有註冊的觀察者 本對象(被觀察者)已更新
*/
void update(Observable o, Object arg);
}
/**
* 這個類表示一個可被觀察的對象,或者模型視圖範例中的“數據”。它可以被繼承,
* 以表示該類 可以被觀察到。
* 一個Observable對象可以有一個或多個觀察者,觀察者可以是實現了Observer接口的任何對象。
* 在一個Observable實例更改之後,調用其notifyObservers()方法,該方法可以通過調用 所有
* 已註冊的Observer對象的update()方法通知其所有觀察者,被觀察的對象已更新。
* @author Chris Warth
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
* @see java.util.Observer
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
* @since JDK1.0
*/
public class Observable {
private boolean changed = false;
/**
* 通過一個Vector來維護 觀察者列表。
* 由於該集合主要涉及元素的增刪操作,所以個人認爲使用LinkedList
* 效果會更好一下
*/
private Vector<Observer> obs;
public Observable() {
obs = new Vector<>();
}
/**
* 註冊 觀察者對象
*/
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
* 移除觀察者對象
*/
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
/**
* 如果此對象已更改,則通知其所有觀察者,然後調用clearChanged()方法 清除更改標記
*/
public void notifyObservers(Object arg) {
// 一個臨時數組緩衝區,用作當前觀察者狀態的快照
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
/**
* 清除觀察者列表,使此對象不再具有任何觀察者
*/
public synchronized void deleteObservers() {
obs.removeAllElements();
}
/**
* 將本對象標記爲已更改
*/
protected synchronized void setChanged() {
changed = true;
}
/**
* 清除本對象的更改標準
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
* 查看本對象是否已更改
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* 返回觀察者列表的長度
*/
public synchronized int countObservers() {
return obs.size();
}
}
責任鏈模式
一般用在消息請求的處理上,如 Netty 的 ChannelHandler組件,Tomcat 對 HTTP 請求的處理。我們當然可以將 請求的處理邏輯都寫在一個類中,但這個類會非常雕腫且不易於維護,不符合開發封閉原則。
在責任鏈模式中,將上述臃腫的請求處理邏輯 拆分到多個 功能邏輯單一的 Handler 處理類中,這樣我們就可以根據業務需求,將多個 Handler 對象組合成一條責任鏈,實現請求的處理。在一條責任鏈中,每個 Handler對象 都包含對下一個 Handler對象 的引用,一個 Handler對象 處理完請求消息(或不能處理該請求)時, 會把請求傳給下一個 Handler對象 繼續處理,依此類推,直至整條責任鏈結束。簡單看一下責任鏈模式的類圖。
Netty 中的應用
在 Netty 中,將 Channel 的數據管道抽象爲 ChannelPipeline,消息在 ChannelPipeline 中流動和傳遞。ChannelPipeline 是 ChannelHandler 的容器,持有 I/O事件攔截器 ChannelHandler 的鏈表,負責對 ChannelHandler 的管理和調度。由 ChannelHandler 對 I/O事件 進行攔截和處理,並可以通過接口方便地新增和刪除 ChannelHandler 來實現不同業務邏輯的處理。下圖是 ChannelPipeline源碼中描繪的責任鏈事件處理過程。
其具體過程處理如下:
-
底層SocketChannel 的 read方法 讀取 ByteBuf,觸發 ChannelRead事件,由 I/O線程 NioEventLoop 調用 ChannelPipeline 的 fireChannelRead()方法,將消息傳輸到 ChannelPipeline中。
-
消息依次被 InboundHandler 1、InboundHandler 2 … InboundHandler N 攔截處理,在這個過程中,任何 ChannelHandler 都可以中斷當前的流程,結束消息的傳遞。
-
當調用 ChannelHandlerContext 的 write()方法 發送消息,消息從 OutbountHandler 1 開始 一直到 OutboundHandler N,最終被添加到消息發送緩衝區中等待刷新和發送。
在 Netty 中將事件根據源頭的不同分爲 InBound事件 和 OutBound事件。InBound事件 通常由 I/O線程 觸發,例如 TCP鏈路 建立和關閉、讀事件等等,分別會觸發相應的事件方法。而 OutBound事件 則一般由用戶主動發起的 網絡I/O操作,例如用戶發起的連接操作,綁定操作和消息發送操作等,也會分別觸發相應的事件方法。由於 netty 中提供了一個抽象類 ChannelHandlerAdapter,它默認不處理攔截的事件。所以,在實際編程過程中,我們只需要繼承 ChannelHandlerAdapter,在我們的 自定義Handler 中覆蓋業務關心的事件方法即可。其源碼如下。
/**
* 它扮演了 責任鏈模式中的 Client角色,持有 構造 並使用 ChannelHandler責任鏈
*/
public interface ChannelPipeline
extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable<Entry<String, ChannelHandler>> {
ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler);
ChannelPipeline addLast(String name, ChannelHandler handler);
ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler);
ChannelPipeline addFirst(ChannelHandler... handlers);
ChannelPipeline addFirst(EventExecutorGroup group, ChannelHandler... handlers);
ChannelPipeline addLast(ChannelHandler... handlers);
ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler... handlers);
ChannelPipeline remove(ChannelHandler handler);
ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
ChannelHandler get(String name);
@Override
ChannelPipeline fireChannelRegistered();
@Override
ChannelPipeline fireChannelUnregistered();
@Override
ChannelPipeline fireChannelActive();
@Override
ChannelPipeline fireChannelInactive();
@Override
ChannelPipeline fireExceptionCaught(Throwable cause);
@Override
ChannelPipeline fireUserEventTriggered(Object event);
@Override
ChannelPipeline fireChannelRead(Object msg);
@Override
ChannelPipeline fireChannelReadComplete();
@Override
ChannelPipeline fireChannelWritabilityChanged();
}
/**
* ChannelHandler本身並不是鏈式結構的,鏈式結構是交由 ChannelHandlerContext
* 進行維護的
*/
public interface ChannelHandler {
void handlerAdded(ChannelHandlerContext ctx) throws Exception;
void handlerRemoved(ChannelHandlerContext ctx) throws Exception;
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;x
}
/**
* DefaultChannelHandlerContext 持有一個 final 的 ChannelHandler對象,
* 其父類 AbstractChannelHandlerContext 是一個雙向鏈表的結構設計,這樣就保證了
* ChannelHandler 的 責任鏈式處理
*/
final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {
private final ChannelHandler handler;
DefaultChannelHandlerContext(
DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
super(pipeline, executor, name, isInbound(handler), isOutbound(handler));
if (handler == null) {
throw new NullPointerException("handler");
}
this.handler = handler;
}
@Override
public ChannelHandler handler() {
return handler;
}
private static boolean isInbound(ChannelHandler handler) {
return handler instanceof ChannelInboundHandler;
}
private static boolean isOutbound(ChannelHandler handler) {
return handler instanceof ChannelOutboundHandler;
}
}
/**
* 很容易看出來,這是一個雙向鏈表的結構設計
*/
abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
implements ChannelHandlerContext, ResourceLeakHint {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannelHandlerContext.class);
volatile AbstractChannelHandlerContext next;
volatile AbstractChannelHandlerContext prev;
......
}
有被“讀過哪些知名的開源項目源碼?”這種問題所困擾過嗎?加入我們,一起通讀互聯網公司主流框架及中間件源碼,成爲強大的“源碼獵人”,目前開放的有 Spring 系列框架、Mybatis 框架、Netty 框架,及Redis中間件等,讓我們一起開拓新的領地,揭開這些源碼的神祕面紗。本項目主要用於記錄框架及中間件源碼的閱讀經驗、個人理解及解析,希望能夠使閱讀源碼變成一件更簡單有趣,且有價值的事情,抽空更新中…(如果本項目對您有幫助,請watch、star、fork 素質三連一波,鼓勵一下作者,謝謝)地址:
https://github.com/doocs/source-code-hunter