面试官:你竟然不晓得Mybatis用了哪些设计模式?

MyBatis框架中的5种设计模式总结 MyBatis框架中使用的5种设计模式分别是:1、建造者模式(生成器模式)。2、工厂模式。3、单例模式。4、代理模式。5、适配器模式。 阅读详情

虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。

Mybatis至少遇到了以下的设计模式的使用。

  • Builder模式:例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;
  • 工厂模式:例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;
  • 单例模式:例如ErrorContext和LogFactory;
  • 代理模式:Mybatis实现的核心,比如MapperProxy、ConnectionLogger,用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果;
  • 组合模式:例如SqlNode和各个子类ChooseSqlNode等;
  • 模板方法模式:例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler;
  • 适配器模式:例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;
  • 装饰者模式:例如Cache包中的cache.decorators子包中等各个装饰者的实现;
  • 迭代器模式:例如迭代器模式PropertyTokenizer;

接下来挨个模式进行解读,先介绍模式自身的知识,然后解读在Mybatis中怎样应用了该模式。

一、Builder模式

Builder模式的定义是“将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。”,它属于创建类模式,一般来说,如果一个对象的构建比较复杂,超出了构造函数所能包含的范围,就可以使用工厂模式和Builder模式,相对于工厂模式会产出一个完整的产品,Builder应用于更加复杂的对象的构建,甚至只会构建产品的一个部分。

在Mybatis环境的初始化过程中,SqlSessionFactoryBuilder会调用XMLConfigBuilder读取所有的MybatisMapConfig.xml和所有的*Mapper.xml文件,构建Mybatis运行的核心对象Configuration对象,然后将该Configuration对象作为参数构建一个SqlSessionFactory对象。

其中XMLConfigBuilder在构建Configuration对象时,也会调用XMLMapperBuilder用于读取*Mapper文件,而XMLMapperBuilder会使用XMLStatementBuilder来读取和build所有的SQL语句。

在这个过程中,有一个相似的特点,就是这些Builder会读取文件或者配置,然后做大量的XpathParser解析、配置或语法的解析、反射生成对象、存入结果缓存等步骤,这么多的工作都不是一个构造函数所能包括的,因此大量采用了Builder模式来解决。

对于builder的具体类,方法都大都用build*开头,比如SqlSessionFactoryBuilder为例,它包含以下方法:

即根据不同的输入参数来构建SqlSessionFactory这个工厂对象。

二、工厂模式

在Mybatis中比如SqlSessionFactory使用的是工厂模式,该工厂没有那么复杂的逻辑,是一个简单工厂模式。

简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。

在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

SqlSession可以认为是一个Mybatis工作的核心的接口,通过这个接口可以执行执行SQL语句、获取Mappers、管理事务。类似于连接MySQL的Connection对象。

可以看到,该Factory的openSession方法重载了很多个,分别支持autoCommit、Executor、Transaction等参数的输入,来构建核心的SqlSession对象。

在DefaultSqlSessionFactory的默认工厂实现里,有一个方法可以看出工厂怎么产出一个产品:

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, Boolean autoCommit) {
	Transaction tx = null;
	try {
		final Environment environment = configuration.getEnvironment();
		final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
		tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
		final Executor executor = configuration.newExecutor(tx, execType);
		return new DefaultSqlSession(configuration, executor, autoCommit);
	}
	catch (Exception e) {
		closeTransaction(tx);
		// may have fetched a connection so lets call // close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }

这是一个openSession调用的底层方法,该方法先从configuration读取对应的环境配置,然后初始化TransactionFactory获得一个Transaction对象,然后通过Transaction获取一个Executor对象,最后通过configuration、Executor、是否autoCommit三个参数构建了SqlSession。

在这里其实也可以看到端倪,SqlSession的执行,其实是委托给对应的Executor来进行的。

而对于LogFactory,它的实现代码:

public final class LogFactory {
	private static Constructor<? extends Log> logConstructor;
	private LogFactory() {
		// disable construction } public static Log getLog(Class<?> aClass) { return getLog(aClass.getName()); }

这里有个特别的地方,是Log变量的的类型是Constructor<? extends Log>,也就是说该工厂生产的不只是一个产品,而是具有Log公共接口的一系列产品,比如Log4jImpl、Slf4jImpl等很多具体的Log。

三、单例模式

单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。

在Mybatis中有两个地方用到单例模式,ErrorContext和LogFactory,其中ErrorContext是用在每个线程范围内的单例,用于记录该线程的执行环境错误信息,而LogFactory则是提供给整个Mybatis使用的日志工厂,用于获得针对项目配置好的日志对象。

ErrorContext的单例实现代码:

public class ErrorContext {
	private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<ErrorContext>();
	private ErrorContext() {
	}
	public static ErrorContext instance() {
		ErrorContext context = LOCAL.get();
		if (context == null) {
			context = new ErrorContext();
			LOCAL.set(context);
		}
		return context;
	}

构造函数是private修饰,具有一个static的局部instance变量和一个获取instance变量的方法,在获取实例的方法中,先判断是否为空如果是的话就先创建,然后返回构造好的对象。

只是这里有个有趣的地方是,LOCAL的静态实例变量使用了ThreadLocal修饰,也就是说它属于每个线程各自的数据,而在instance()方法中,先获取本线程的该实例,如果没有就创建该线程独有的ErrorContext。

四、代理模式

代理模式可以认为是Mybatis的核心使用的模式,正是由于这个模式,我们只需要编写Mapper.java接口,不需要实现,由Mybatis后台帮我们完成具体SQL的执行。

代理模式(Proxy Pattern):给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。

代理模式包含如下角色:

  • Subject:抽象主题角色
  • Proxy:代理主题角色
  • RealSubject:真实主题角色

这里有两个步骤,第一个是提前创建一个Proxy,第二个是使用的时候会自动请求Proxy,然后由Proxy来执行具体事务。

当我们使用Configuration的getMapper方法时,会调用mapperRegistry.getMapper方法,而该方法又会调用mapperProxyFactory.newInstance(sqlSession)来生成一个具体的代理:

public class MapperProxyFactory<T> {
	private final Class<T> mapperInterface;
	private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();
	public MapperProxyFactory(Class<T> mapperInterface) {
		this.mapperInterface = mapperInterface;
	}
	public Class<T> getMapperInterface() {
		return mapperInterface;
	}
	public Map<Method, MapperMethod> getMethodCache() {
		return methodCache;
	}
	@SuppressWarnings("unchecked") protected T newInstance(MapperProxy<T> mapperProxy) {
		return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] {
			mapperInterface
		}
		, mapperProxy);
	}
	public T newInstance(SqlSession sqlSession) {
		final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
		return newInstance(mapperProxy);
	}
}

在这里,先通过T newInstance(SqlSession sqlSession)方法会得到一个MapperProxy对象,然后调用T newInstance(MapperProxy mapperProxy)生成代理对象然后返回。

而查看MapperProxy的代码,可以看到如下内容:

public class MapperProxy<T> implements InvocationHandler, Serializable {
	@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		try {
			if (Object.class.equals(method.getDeclaringClass())) {
				return method.invoke(this, args);
			} else if (isDefaultMethod(method)) {
				return invokeDefaultMethod(proxy, method, args);
			}
		}
		catch (Throwable t) {
			throw ExceptionUtil.unwrapThrowable(t);
		}
		final MapperMethod mapperMethod = cachedMapperMethod(method);
		return mapperMethod.execute(sqlSession, args);
	}

非常典型的,该MapperProxy类实现了InvocationHandler接口,并且实现了该接口的invoke方法。

通过这种方式,我们只需要编写Mapper.java接口类,当真正执行一个Mapper接口的时候,就会转发给MapperProxy.invoke方法,而该方法则会调用后续的sqlSession.cud>executor.execute>prepareStatement等一系列方法,完成SQL的执行和返回。

五、组合模式

组合模式组合多个对象形成树形结构以表示“整体-部分”的结构层次。

组合模式对单个对象(叶子对象)和组合对象(组合对象)具有一致性,它将对象组织到树结构中,可以用来描述整体与部分的关系。同时它也模糊了简单元素(叶子对象)和复杂元素(容器对象)的概念,使得客户能够像处理简单元素一样来处理复杂元素,从而使客户程序能够与复杂元素的内部结构解耦。

在使用组合模式中需要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。

Mybatis支持动态SQL的强大功能,比如下面的这个SQL:

<UPDATE id="update" parameterType="org.format.dynamicproxy.mybatis.bean.User">UPDATE users <trim prefix="SET" prefixOverrides=",
        "> <if test="name != null
        AND name != ''"> name = #{name} </if> <if test="age != null
        AND age != ''"> , age = #{age} </if> <if test="birthday != null
        AND birthday != ''"> , birthday = #{birthday} </if> </trim>
WHERE id = ${id}</update> 

在这里面使用到了trim、if等动态元素,可以根据条件来生成不同情况下的SQL;

在DynamicSqlSource.getBoundSql方法里,调用了rootSqlNode.apply(context)方法,apply方法是所有的动态节点都实现的接口:

public interface SqlNode {
	Boolean apply(DynamicContext context);
}

对于实现该SqlSource接口的所有节点,就是整个组合模式树的各个节点:

组合模式的简单之处在于,所有的子节点都是同一类节点,可以递归的向下执行,比如对于TextSqlNode,因为它是最底层的叶子节点,所以直接将对应的内容append到SQL语句中:

@Overridepublic Boolean apply(DynamicContext context) {
	GenericTokenParser parser = createParser(new BindingTokenParser(context, injectionFilter));
	context.appendSql(parser.parse(text));
	return true;
}

但是对于IfSqlNode,就需要先做判断,如果判断通过,仍然会调用子元素的SqlNode,即contents.apply方法,实现递归的解析。

@Overridepublic Boolean apply(DynamicContext context) {
	if (evaluator.evaluateBoolean(test, context.getBindings())) {
		contents.apply(context);
		return true;
	}
	return false;
}

#六、模板方法模式

模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术。

模板方法模式需要开发抽象类和具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。代表这些具体逻辑步骤的方法称做基本方法(primitive method);而将这些基本方法汇总起来的方法叫做模板方法(template method),这个设计模式的名字就是从此而来。

模板类定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

在Mybatis中,sqlSession的SQL执行,都是委托给Executor实现的,Executor包含以下结构:

其中的BaseExecutor就采用了模板方法模式,它实现了大部分的SQL执行逻辑,然后把以下几个方法交给子类定制化完成:

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;

该模板方法类有几个子类的具体实现,使用了不同的策略:

  • 简单SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。(可以是Statement或PrepareStatement对象)

  • 重用ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。(可以是Statement或PrepareStatement对象)

  • 批量BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理的;BatchExecutor相当于维护了多个桶,每个桶里都装了很多属于自己的SQL,就像苹果蓝里装了很多苹果,番茄蓝里装了很多番茄,最后,再统一倒进仓库。(可以是Statement或PrepareStatement对象)

比如在SimpleExecutor中这样实现update方法:

@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);
	}
}

七、适配器模式

适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。

在Mybatsi的logging包中,有一个Log接口:

public interface Log {
	Boolean isDebugEnabled();
	Boolean isTraceEnabled();
	void error(String s, Throwable e);
	void error(String s);
	void debug(String s);
	void trace(String s);
	void warn(String s);
}

该接口定义了Mybatis直接使用的日志方法,而Log接口具体由谁来实现呢?Mybatis提供了多种日志框架的实现,这些实现都匹配这个Log接口所定义的接口方法,最终实现了所有外部日志框架到Mybatis日志包的适配:

比如对于Log4jImpl的实现来说,该实现持有了org.apache.log4j.Logger的实例,然后所有的日志方法,均委托该实例来实现。

public class Log4jImpl implements Log {
	private static final String FQCN = Log4jImpl.class.getName();
	private Logger log;
	public Log4jImpl(String clazz) {
		log = Logger.getLogger(clazz);
	}
	@Override public Boolean isDebugEnabled() {
		return log.isDebugEnabled();
	}
	@Override public Boolean isTraceEnabled() {
		return log.isTraceEnabled();
	}
	@Override public void error(String s, Throwable e) {
		log.log(FQCN, Level.ERROR, s, e);
	}
	@Override public void error(String s) {
		log.log(FQCN, Level.ERROR, s, null);
	}
	@Override public void debug(String s) {
		log.log(FQCN, Level.DEBUG, s, null);
	}
	@Override public void trace(String s) {
		log.log(FQCN, Level.TRACE, s, null);
	}
	@Override public void warn(String s) {
		log.log(FQCN, Level.WARN, s, null);
	}

八、装饰者模式

装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式。

在mybatis中,缓存的功能由根接口Cache(org.apache.ibatis.cache.Cache)定义。

整个体系采用装饰器设计模式,数据存储和缓存的基本功能由PerpetualCache(org.apache.ibatis.cache.impl.PerpetualCache)永久缓存实现,然后通过一系列的装饰器来对PerpetualCache永久缓存进行缓存策略等方便的控制。

如下图:

用于装饰PerpetualCache的标准装饰器共有8个(全部在org.apache.ibatis.cache.decorators包中):

  • FifoCache:先进先出算法,缓存回收策略
  • LoggingCache:输出缓存命中的日志信息
  • LruCache:最近最少使用算法,缓存回收策略
  • ScheduledCache:调度缓存,负责定时清空缓存
  • SerializedCache:缓存序列化和反序列化存储
  • SoftCache:基于软引用实现的缓存管理策略
  • SynchronizedCache:同步的缓存装饰器,用于防止多线程并发访问
  • WeakCache:基于弱引用实现的缓存管理策略

另外,还有一个特殊的装饰器TransactionalCache:事务性的缓存。

正如大多数持久层框架一样,mybatis缓存同样分为一级缓存和二级缓存。

一级缓存,又叫本地缓存,是PerpetualCache类型的永久缓存,保存在执行器中(BaseExecutor),而执行器又在SqlSession(DefaultSqlSession)中,所以一级缓存的生命周期与SqlSession是相同的。

二级缓存,又叫自定义缓存,实现了Cache接口的类都可以作为二级缓存,所以可配置如encache等的第三方缓存。二级缓存以namespace名称空间为其唯一标识,被保存在Configuration核心配置对象中。

二级缓存对象的默认类型为PerpetualCache,如果配置的缓存是默认类型,则mybatis会根据配置自动追加一系列装饰器。

Cache对象之间的引用顺序为:

SynchronizedCache–>LoggingCache–>SerializedCache–>ScheduledCache–>LruCache–>PerpetualCache

九、迭代器模式

迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

Java的Iterator就是迭代器模式的接口,只要实现了该接口,就相当于应用了迭代器模式:

比如Mybatis的PropertyTokenizer是property包中的重量级类,该类会被reflection包中其他的类频繁的引用到。这个类实现了Iterator接口,在使用时经常被用到的是Iterator接口中的hasNext这个函数。

public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
	private String name;
	private String indexedName;
	private String index;
	private String children;
	public PropertyTokenizer(String fullname) {
		int delim = fullname.indexOf('.');
		if (delim > -1) {
			name = fullname.substring(0, delim);
			children = fullname.substring(delim + 1);
		} else {
			name = fullname;
			children = null;
		}
		indexedName = name;
		delim = name.indexOf('[');
		if (delim > -1) {
			index = name.substring(delim + 1, name.length() - 1);
			name = name.substring(0, delim);
		}
	}
	public String getName() {
		return name;
	}
	public String getIndex() {
		return index;
	}
	public String getIndexedName() {
		return indexedName;
	}
	public String getChildren() {
		return children;
	}
	@Override public Boolean hasNext() {
		return children != null;
	}
	@Override public PropertyTokenizer next() {
		return new PropertyTokenizer(children);
	}
	@Override public void remove() {
		throw new UnsupportedOperationException( "Remove is not supported, as it has no meaning in the context of properties.");
	}
}

可以看到,这个类传入一个字符串到构造函数,然后提供了iterator方法对解析后的子串进行遍历,是一个很常用的方法类。

Java_supermanNO1:专注于Java开发技术的研究与知识分享!

————END————

  • 点赞(编辑不易,感谢您的支持)

  • …

  • 转发(分享知识,传播快乐)

  • …

  • 关注(每天更新Java开发技术)

  • …

Gamma变换算法之Matlab&FPGA实现 Gamma映射原理 什么是Gamma曲线 人眼的感光与光强并不是呈线性关系的,而是呈非线性关系(指数型关系,如下图左-曲线。在低照度下,人眼更容易分辨出亮度的变化,随着照度的增加,人眼不易分辨出亮度的变化。而图像传感器与输入光强呈线性关系(如下图左-直线)。从图中可见,当传感器感光在20%左右时,人眼感光响应达到了50%,人眼对低照度的变化更为敏感。从下图右侧可见,Reference Tone为人眼感光50%的亮度,而传感器在感光50%时则相对暗的多(见Select,近似中性灰)。这种将原始图像通过映射操 阅读详情

相关推荐

ST7102驱动移植与调试实战

本文详细介绍了在君正T40平台上移植和调试ST7102 LCD驱动芯片的实战经验。内容涵盖硬件接口配置、时序参数调整、寄存器初始化序列编写及常见问题解决,重点解析了ST7102单芯片集成显示与触控功能的特性,为嵌入式设备显示驱动开发提供实用指南。

k6l7m8n9的博客 1415

Mybatis中使用了哪些设计模式

Mybatis 中使用了10种设计模式,其中创建型模式3种(工厂、单例、建造者),结构型模式4种(适配器、代理、组合、装饰器),行为型模式3种(模板、策略、迭代器)

qq5621的博客 4899

【深度解析】信息素养提升实践活动(附:历年获奖作品分析)

全国师生信息素养提升实践活动是由教育部教育技术与资源发展中心(中央电化教育馆)主办,面向全国师生的一项信息化交流展示活动。

m0_74417957的博客 9654

面试官:Mybatis 使用了哪些设计模式?

虽然我们都知道有20多个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。 Mybatis至少遇到了以下的设计模式的使用: Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder; 工厂模式,例如SqlSessionFactory、ObjectF

weixin_47531845的博客 720

从零到实战:用QCustomPlot在QT中绘制动态曲线图(含OpenGL加速配置)

本文详细介绍了如何在QT中使用QCustomPlot库绘制动态曲线图,并配置OpenGL加速以提升渲染性能。从环境搭建、动态数据可视化到OpenGL加速配置,手把手教你实现工业级动态曲线监控系统,适用于大数据量实时展示场景。

weixin_29019241的博客 354

Solidworks二次开发(C# .NET API):从零构建装配体与虚拟零件

本文详细介绍了使用C#进行Solidworks二次开发,从零构建装配体与虚拟零件的完整流程。通过.NET API实现设计自动化,涵盖环境搭建、核心对象模型、虚拟零件创建与外部化保存等关键技术,帮助工程师将重复性建模工作程序化,大幅提升设计效率与标准化水平。

alice7model的博客 607

Mybatis源码解读-设计模式总结

虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。 Mybatis至少遇到了以下的设计模式的使用: Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatemen...

蚂蚁学Python 1956

Linux虚拟机mysql安装教程(详细步骤)出现了一个错误:依赖检测失败

Linux虚拟机安装mysql的详细步骤(有报错预警哦)

m0_74953387的博客 5260

mybatis 9种设计模式

mybatis 设计的设计模式: 1.builder 设计模式 例如: SqlSessionFactoryBuilder.xmlConfigbuilder,xmlMapperBuilder,xmlStatementBuilder,CacheBuilder 2.工厂设计模式,例如: SqlsessionFactory,ObjectFactory,MapperProxyFactory 3.单利...

厚积薄发的博客 727

用AI+Playwright实现零代码UI自动化测试:以登录页面为例的实战指南

本文详细介绍了如何利用AI与Playwright结合实现零代码UI自动化测试,特别以登录页面为例进行实战演示。通过自然语言描述生成测试脚本,大幅降低技术门槛,提升测试效率,并支持跨浏览器验证。适合非技术人员快速上手专业级自动化测试。

weixin_28842269的博客 403

数据行小于列索引,内部模式表示可能存在问题

通过检查数据源的完整性和一致性,检查Debezium配置,检查列映射以及启用调试模式和日志记录,您应该能够解决这个错误。请注意,具体的解决方法可能因您的具体情况而异,因此您可能需要根据问题的根本原因进行适当的调整和修复。如果问题仍然存在,您可能需要进一步检查您的数据和配置,并根据具体情况进行调整和修复。在Debezium中,您可以使用列重命名和列映射来定义源和目标之间的列映射关系。通过检查日志,您可以查看详细的错误信息和堆栈跟踪,从而更好地理解问题的根本原因。首先,我们应该检查数据源的完整性和一致性。

XbtoMemory的博客 731

面试官:你竟然不晓得Mybatis用了哪些设计模式?

作者:疯狂的蚂蚁 来源:crazyant.net/2022.html虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模...

公众号-老炮说Java 274

Open3D(C++) 统计滤波【2025最新版】

 统计滤波器用于去除明显离群点,离群点往往由测量噪声引入,其特征是在空间中分布稀疏,可以理解为:每个点都表达一定信息量,某个区域点越密集则可能信息量越大。噪声信息属于无用信息,信息量较小。所以离群点表达的信息可以忽略不计。...

点云侠的博客 1121

mybatis 调用类的函数_面试官:你竟然不晓得Mybatis用了哪些设计模式?

作者:疯狂的蚂蚁 来源:crazyant.net/2022.html虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。Mybatis至少遇到了以下的设计模式的使用。Builder模式,例如SqlSessionFactoryBuilder、XMLConfig...

weixin_39526706的博客 56

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

c++ builder formclose不执行_面试官:你竟然不晓得Mybatis用了哪些设计模式?

前语:不要为了读文章而读文章,一定要带着问题来读文章,勤思考。在此,建议大家为本公众号加“星标”。如文章写得好,望大家阅读后在右下边“在看”处点个赞,以示鼓励!作者:疯狂的蚂蚁 来源:https://0x9.me/Nc1FQ--------------------------先来发一个我厂的招聘信息,感兴趣的同学欢迎来私聊哦,base:成都。---------------------...

weixin_33226548的博客 124

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

MyBatis中用到的设计模式

面试官:“谈谈MyBatis中都用到了那些设计模式?”。 疯狂的蚂蚁JavaGuide 本文转载自:https://dwz.cn/KFgol1De由JavaGuide整理排版。 虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。 目录 面试官:“谈...

Angus 9882

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

面试官问你MyBatis中有哪些设计模式,把这篇文章发给他

本文转载自:https://dwz.cn/KFgol1De 由JavaGuide整理排版。之前总结过一篇Spring中用到了哪些设计模式:《面试官:“谈谈Spring中...

WantFlyDaCheng的博客 210

面试官:“谈谈MyBatis中都用到了那些设计模式?”。

面试官:“谈谈MyBatis中都用到了那些设计模式?”。 虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。 Mybatis至少遇到了以下的设计模式的使用: 1.Builder模式 : 例如 SqlSessionFactoryBuilder、XMLConfigBuild...

歲月的孤獨 310

面试官:读过 Mybatis源码吗?知道用了那9种设计模式吗?

点击上方“码农进阶之路”,选择“设为星标”回复“面经”获取面试资料来源:http://crazyant.net/2022.html虽然我们都知道有26个设计模式,但是大多停留在概念层面,...

二师兄撒欢之地 1万+

面试官:Mybatis里的设计模式有哪些?脱口而出8种

点击上方“java大数据修炼之道”,选择“设为星标”优质文章和精品资源, 第一时间送达关注公众号后台回复资源获取实战教学资料+视频哈喽,各位新来的小伙伴们,大家好!由于公众号做了改版,为...

hello world! 503

面试官:说一下Mybatis 使用了哪些设计模式?

虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解...

java面试笔试 599

面试官: Mybatis 中使用了哪 9 种设计模式

我是猿人,一个热爱技术、热爱编程的IT猿。技术是开源的,知识是共享的!写作是对自己学习的总结和记录,如果您对 Java、分布式、微服务、中间件、Spring Boot、Spring Clo...

猿码天地 293

面试官:Mybatis运用了哪些设计模式?

虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。 Mybatis至少遇到了以下的设计模式的使用: Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder; 工厂模式,例如SqlSessionFactory、Ob

wangzhiping44的专栏 197

mybatis批量update_面试官:Mybatis用到了哪些设计模式?系列二

面试官:Mybatis用到了哪些设计模式?6、模板方法模式模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术。模板方法模式需要开发抽象类和具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。代表这些具体逻辑步骤的方法称做基本方法(primitive method);而将这些基本方法汇总起来的方法叫做模板方法(...

weixin_39615984的博客 124
上一篇: 如何解决跨域问题,来看看阿里P7架构师是怎么解决的,你有遇到吗?
下一篇: 分布式消息队列差异化总结,太全了!
Java_supermanNO1
博客等级 码龄7年 1170粉丝 329原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值