接口分析,以简单的mybatis接口为例

关于接口的思考


在所有的框架当中,接口是少数的,实现类是大多数的


所以入手的时候,当我们明白提炼的接口是怎么回事的时候。
那就意味着你差不多读懂了这个框架的一半。


所以我们可以以mybatis几个包的接口来逐个分析
这个框架搭起来的时候它的意图是怎样的。
这样将大大减少我们分析一个框架的工作量


从org.apache.ibatis包开始读起
这里再插一个,接口之所以能代表很多的含义和背后的意图,在于它的无状态特性。
没有数据存储,但是随着新的接口规范的出现,除了常量以外,现在貌似也可以有接口的默认实现。
这样就意味着。接口的重要性,实际上得到进一步的提升。


annatations 注解包
参数注解 arg:
包含了代表的
column String类型 默认空字符""
javaType Class类型 默认是void.class
jdbcType JdbcType类型,默认枚举的UNDEFINED
typeHander Class类型 一看就知道是类型转换器
select String 查询别名?
resultMap String  映射的resultMap别名
name() String  列的名称


AutoMapConstructor 就一个空注解,用来做啥的呢?
自动映射的构造器,注解在构造器上的,因为
@Target({ElementType.CONSTRUCTOR})


CacheNamespace 缓存空间注解,用来注解在类上的,包含:
implementation() Class 指定他的实现类
eviction Class 失效的策略 默认LruCache.class 最少使用的机制
flushInteraval 刷新间隔 long = 0
size() 默认 int = 1024
是否读写 readWrite true
是否阻塞 blocking false 不阻塞
默认的一些属性  properities() 默认{} 返回的是另一个接口 注解Property,这里包含了name 和value的元信息
用来给实现对象准备的。


CacheNamespaceRef 缓存空间引用注解
name 名称
value Class 引用的类 void.class 默认


Case 这个注解有意思,因为他的target为{}
这说明这个直接是用来和其他混合使用的,他不能单独使用。
包含
value  String
type() Class<?>
results Result[] 返回注解
constructArgs() Arg[] 返回注解


用在发那个发上
ConstructArgs 这个注解只有一个方法
vlaue() 返回Arg[] 注解arg[] 数组


Delete 注解 用在方法上
value() String数组


MethodProvider 用在方法上
Type Class<?> 和类
method String 指定方法名称


Flush 用来执行刷新mapper状态
没有方法


Insert
同delete 
String[] value()


InsertProvider 同MethodProvider


Lang
Class<?> value


Many 同case的作用域


select()  这应该是表名
FetchType fetchType() default FetchType.DEFAULT 这是枚举指定
包含了懒加载LAZY EAGER DEFAULT 饥饿加载和默认加载


MapKey 用于方法
value 映射的key


Mapper 用于类 方法 属性 入参
无值


one 同many


Options 用在方法上注解
这个比较多
 内置了一个枚举类FlushCachePolicy
 刷新 statement语句


useCache 是否用缓存 默认true
刷新缓存的策略,默认 FlushCachePolicy.DEFAULT
结果集类型 默认 ResultSetType.FORWARD_ONLY 这是jdbc接口里的


Param注解,用来指定 value 用在入参上
Property 指定属性 name() value() String类型,不能单独使用
结果映射
Result
id()  false
column() ""
javaType  void.class
jdbcType  JdbcType.UNDEFINED
typeHandler() UnknownTypeHandler.class转换处理
One one() default @One;
Many many() default @Many; 一对多注解
ResultMap 注解方法上
value() String[] 数组


Results 注解方法上
id() ""  resultMap的名称
Result[] value  result注解集


ResultType 方法上 value() Class<?>


Select
value() String[] 注解返回数组


SelectKey 注解方法上
String[] statement();
String keyProperty();
String keyColumn() default "";
boolean before();
Class<?> resultType();
StatementType statementType() default StatementType.PREPARED;
这个是枚举,分为回调、预编译和正在进行的语句。
SelectProvider 同上面的


类型辨别注解 Discriminator 方法上
column() 列String
javaType
和jdbcType
转换Hander
Case[] cases()
update 和 updateProvider 同上


binding包,绑定包,这个一看就知道是mapper与接口的绑定
一个绑定异常 BindingException 继承了它自己写的持久化异常
加上序列号,持久化异常继承Ibatsi异常


MapperMethod 映射方法类
属性 SqlCommand 和方法标记 MethodSignature(包含返回值和入参)
两个分别是sql语句的封装类和执行method的封装类
方法中的两个静态内部类
就一个公开的构造方法,config method 和 mapperInterface
下面是执行方法 execute(sqlSession, args[])
返回Object
这是一个用来通过Switch分流的方法
分别分成 select update delete insert flush刷缓存,
默认就是抛异常,最后返回结果,里面所有的执行最后委托给了sqlSession去执行


MapperProxy 这个是代理类,实现了啥?
jdk的proxy方法代理 InvocationHandler 和序列化,加泛型T
属性
sqlSession
class<T> mapperInterface
Map<Method,MapperMethod> 方法和MapperMethod的缓存
唯一的构造方法就是传入上面的参数。


执行原则就是:
如果是类
Object.class.equals(method.getDeclaringClass())
就以本对象来执行,以及上面的args参数


如果是抽象类,就用另外的方式来执行这个方法。
如果是上面其他以外的,那么就缓存mapperMethod
然后通过mapperMethod.execute去执行。
所以这个是代理方法的执行。


MapperProxyFactory 代理类的生成
属性:
mapperInterface Class
Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>() 
方法对应的MapperMethod缓存


protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }
  这个方法生成了代理类
 
 由公开的方法 public T newInstance(SqlSession sqlSession)
 返回
 
 MapperRegistry 这个类用来存储
 MapperProxyFactory 对应的class 
 Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();


 提供公开的方法,用来通过ClassType返回对应的代理类
 可以增加指定的Mapper
 或者扫描该包的下的Mapper,包里符合ClassType的Mapper接口
 
 
 说好的分析接口,怎么又分析类了????????????
 走偏了,重新分析
 
 分析这个包下的,哦,没有接口
 
 下一个包
 builder中的唯一接口
 InitializingObject
 void initialize() throws Exception; 唯一的方法
 初始化一个实例的含义
 这个没有实现类,所以没用上??
 
 
 cache缓存包
 提供了一个接口
 Cache 缓存接口
 定义了几个常见的方法
 clear()
 getObject(key)
 putObject(key,value)
 removeObject(key)
 
 getId 获得缓存Id
 getSize  缓存尺寸
 getReadWriteLock 读写锁
 
 这个接口厉害了,实现了一大堆的不同缓存实现策略。看看默认使用的LRU吧
 
使用了装饰器模式,在已经实现的缓存中,再包一层
public class LruCache implements Cache {


  private final Cache delegate;
  private Map<Object, Object> keyMap;
  private Object eldestKey;
  
  这个被装饰的实现类
  PerpetualCache 这个类,是它的本来实现
  
  private String id;


  private Map<Object, Object> cache = new HashMap<Object, Object>();
用hashMap存数据,装饰类,就使用了一些淘汰策略、


cursor包,里面就定义了一个Cusor游标,继承Closeable 和 迭代器接口


 isOpen() true说明开始查找了
 isConsumed()  说明查完了
 getCurrentIndex() 得到当前下标,-1表示第一个对象没取到,取到了是0下标
 
 dataSource包,
 这个包的接口就一个 
 DataSourceFactory  数据源工厂
 void setProperties(Properties props) 设置数据源参数
 DataSource getDataSource() 获得数据源
 下面三个实现
 不采用数据连接池的实现 UnpooledDataSourceFactory
 采用数据连接池的实现  PooledDataSourceFactory
 还有一个JNDI的工厂实现 JndiDataSourceFactory
 这个工厂提供的方法就是把dataSource get出来
 而这个dataSource就包含了两种,连接池版本的,和现成创建连接的


 exception包没接口,跳过
 executor包接口,有好几个
 
 最外层:
 Executor 执行者接口
 实现了对数据库的操作
 int update(MappedStatement ms, Object parameter) 语句和参数执行
 查询以及缓存,还有查询的起始及条数,结果转换器,执行的sql
 <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
 没有缓存的查询
 List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
 批量结果,执行
 List<BatchResult> flushStatements() throws SQLException;
  提交和回滚
  void commit(boolean required) throws SQLException;
  void rollback(boolean required) throws SQLException;
 创建缓存的key
  CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
是否有这个缓存
boolean isCached(MappedStatement ms, CacheKey key);
清缓存
void clearLocalCache();
延迟加载
void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
获得事务
   Transaction getTransaction();
   关闭,是否强制回滚
   void close(boolean forceRollback);
   设置包装类
   void setExecutorWrapper(Executor executor);


以上接口,用一个抽象类实现,然后用缓存类再实现
Executor --> BaseExecutor --> CachingExecutor 喜欢用装饰模式啊


KeyGenerator key生成器接口
生成前动作
void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter);


生成后动作
void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter);


接口的实现三个,
典型的是 查询key的设置,会存储在keyStatement的String[]数组中
全部存储在 MappedStatement这个对象中,而这个对象又会被存在config当中
全局config可以用来继承,然后写下其中的一些方法,取出mybatis的相关信息
能封装yeah!


loader中的接口
ProxyFactory 
void setProperties(Properties properties);
Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
设置属性
和创建代理类
有两个实现,一个的CgLib的实现,一个是字节码增强的实现


WriteReplaceInterface
这个接口还没有用到


parameter中的接口
ParameterHandler
两个方法
获得参数和往ps中设置参数
  Object getParameterObject();
  void setParameters(PreparedStatement ps)throws SQLException;
  有一个default实现类
 
ResultSetHandler 结果处理器
三个方法
根据stmt获得处理后的结果
<E> List<E> handleResultSets(Statement stmt) throws SQLException; 
根据语句得到处理后的游标
<E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;
处理输出的结果参数
void handleOutputParameters(CallableStatement cs) throws SQLException;


有一个默认实现
DefaultResultSetHandler




StatementHandler 接口,用来实现语句的执行
准备语句
Statement prepare(Connection connection, Integer transactionTimeout)throws SQLException;

确定参数
void parameterize(Statement statement)throws SQLException;
批执行 
void batch(Statement statement)throws SQLException;
更新
int update(Statement statement)throws SQLException;
查询
<E> List<E> query(Statement statement, ResultHandler resultHandler)throws SQLException;
查询游标
<E> Cursor<E> queryCursor(Statement statement)throws SQLException;
获得执行语句
BoundSql getBoundSql();
获得参数处理器
ParameterHandler getParameterHandler();
两个实现
BaseStatementHandler

RoutingStatementHandler 这个照样采用了装饰器模式,以上面的Handler为被装饰类




下面是javassit java动态类库,提供了一些工具类
外层两个接口 ClassPath 和 Translator
ClassPath抽象出两个方法
InputStream openClassfile(String s) 根据字符串classFile转换为输入流
URL find(String s) 找url地址
void close() 关闭
这里有一系列的实现,这都是用来加载资源的


Translator 有两个实现,主要是利用动态字节码技术


这个包是工具类


jdbc没接口
lang有两个注解注解 java7版本和java8版本
UsesJava7
UsesJava8


log包中
抽象了log接口
只提供过了 isDebugEnabled 和 isTraceEnabled两个boolean判断
error(s,e)
error(s)
debug(s)
trace(s)
warn(s) 几个方法


根据工厂类,可以更换不同的日志系统


mapping包
DatabaseIdProvider  一个默认实现
SqlSource  三个实现类,不同的sql写法
两个接口
前者提供:
void setProperties(Properties p); 设置参数
String getDatabaseId(DataSource dataSource) throws SQLException; 获得数据源信息


后者提供
BoundSql getBoundSql(Object parameterObject);根据入参获得真正的sql




ognl包


ehhance子包里,
ExpressionAccessor接口
获取对象到上下文
    java.lang.Object get(org.apache.ibatis.ognl.OgnlContext ognlContext, java.lang.Object o);
设置对象
    void set(org.apache.ibatis.ognl.OgnlContext ognlContext, java.lang.Object o, java.lang.Object o1);
设置表达式
    void setExpression(org.apache.ibatis.ognl.Node node);


本地引用
public interface LocalReference {
    java.lang.String getName();


    java.lang.String getExpression();


    java.lang.Class getType();
}


OgnlExpressionCompiler 编译器


OrderedReturn 顺序返回 得到核心表达式,得到最后表达式
    java.lang.String getCoreExpression();


    java.lang.String getLastExpression();


ClassCache缓存接口
setClassInspector 设置class检查器
clear 清空
getSize 获得大小
get(class) 获得某class
put(class object) 存储某class对应的实例


ClassCacheInspector 类缓存检查器
 boolean shouldCache(java.lang.Class aClass) 需要被缓存吗
 
 ClassResolver 类接口器 类似于class forName 这个肯定要委托给jdk来
 java.lang.Class classForName(java.lang.String s, java.util.Map map) throws java.lang.ClassNotFoundException;


 ElementsAccessor 这个接口 遍历接口 存取器
 java.util.Enumeration getElements(java.lang.Object o) throws org.apache.ibatis.ognl.OgnlException;


 JavaSource接口 设置到上下文中,或者获取
 String toGetSourceString(OgnlContext ognlContext, Object o);
 String toSetSourceString(OgnlContext ognlContext, Object o);
 
 这里暂不分析了,有比较多的接口
 针对的的是Member Method Node NodeType  PropertyAccessor TypeConverter
 类似,但定义的方法有所不同
 
 parsing包里的 
 
 TokenHandler 占位符处理,这个接口,xml解析相关
 
 plugin扩展包
 Interceptor 解释器接口 形成解释器链
 Intercepts 解释器注解
 Signature 签名注解
 
 责任链模式
 
 
 反射的包 reflectionFactory
 ReflectorFactory 反射工厂
 
 是否缓存,设置缓存,根据classType得到反射类
 其他三个接口方法
 Invoker  包含了执行invoke 和 getType class的类型 两个方法,包含三个实现类
 GetFieldInvoker MethodInvoker SetFieldInvoker 这三个实现类
 ObjectWrapper 定义的方法比较多,主要的是
 get set方法的判断,以及是否是集合的判断,实现类有base 和collectionWrapper类
 
 ObjectWrapperFactory 都是用一个工厂类,来掩蔽构造器细节。
 两个方法,有他的包装类吗,根据元信息返回他的包装类
 boolean hasWrapperFor(Object object);
 ObjectWrapper getWrapperFor(MetaObject metaObject, Object object);
 
 脚本的包 scripting
 LanguageDriver 接口
 ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
 SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
 SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);
用来解析xml中的脚本,获取相应的sql语句


SqlNode 接口 应用动态上下文
boolean apply(DynamicContext context);


session会话包


SqlSessionFactory 工厂 生成sqlSession对象
  SqlSession openSession();得到一个sqlSession对象
  SqlSession openSession(boolean autoCommit);
  SqlSession openSession(Connection connection);
  SqlSession openSession(TransactionIsolationLevel level);


  SqlSession openSession(ExecutorType execType);
  SqlSession openSession(ExecutorType execType, boolean autoCommit);
  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType, Connection connection);
  Configuration getConfiguration();得到配置类


SqlSession 接口继承了Closeable  默认实现和sqlSessionManager管理类实现代理类

一系列访问数据库的方法 
  <T> T selectOne(String statement);
  <T> T selectOne(String statement, Object parameter);
  <E> List<E> selectList(String statement);
  <E> List<E> selectList(String statement, Object parameter);
  <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
  <K, V> Map<K, V> selectMap(String statement, String mapKey);
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
  <T> Cursor<T> selectCursor(String statement);
  <T> Cursor<T> selectCursor(String statement, Object parameter);
  <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);
  void select(String statement, Object parameter, ResultHandler handler);
  void select(String statement, ResultHandler handler);
  void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
  int insert(String statement);
  int insert(String statement, Object parameter);
  int update(String statement);
  int update(String statement, Object parameter);
  int delete(String statement);
  int delete(String statement, Object parameter);
  void commit();
  void commit(boolean force);
  void rollback();
  void rollback(boolean force);
  List<BatchResult> flushStatements();
  void close();
  void clearCache();
  Configuration getConfiguration();
  <T> T getMapper(Class<T> type);
  Connection getConnection();
  
  接口 ResultHandler<T> 默认实现和包装类实现
  void handleResult(ResultContext<? extends T> resultContext);处理上下文
  
  接口 ResultContext<T> 有一个默认实现
  T getResultObject();
  int getResultCount();
  boolean isStopped();
  void stop();
  
  
  事务包 transaction
  Transaction 接口 两个实现类
    Connection getConnection() throws SQLException;
void commit() throws SQLException;
    void rollback() throws SQLException;
void close() throws SQLException;
Integer getTimeout() throws SQLException;

  TransactionFactory 接口 两个对应的实现类
    void setProperties(Properties props);
Transaction newTransaction(Connection conn);
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);

  type包
Alias 类注解 value

MappedJdbcTypes 类注解
注解 JdbcType[] value
includeNullJdbcType() false

MappedTypes 注解类
Class<?>[] value()

TypeHandler类型处理接口 base抽象实现,调用的留给子类去实现,不同的数据类型对应不同的处理方法
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
 
  这上面不同的数据类型对应到不同的处理器,数组的,bob的等等。
  
  
  

猜你喜欢

转载自blog.csdn.net/u011402896/article/details/80055263