MyBatis设计模式之构建者、工厂、代理模式

MyBatis设计模式之构建者、工厂、代理模式

一、MyBatis整体架构与设计模式

MyBatis作为一款优秀的持久层框架,其代码中运用了多种经典的设计模式。这些设计模式的应用,使得MyBatis具有良好的扩展性、灵活性和可维护性。

1.1 MyBatis整体架构

MyBatis采用了分层架构设计,从上到下主要包括:

  • 应用层:用户应用程序
  • 接口层:SqlSession、Mapper接口
  • 核心处理层:SQL解析、执行、结果映射
  • 基础支撑层:反射、类型处理、日志、缓存、事务等
  • 数据层:数据源、连接池、JDBC驱动

在这些层次中,设计模式被广泛应用,贯穿整个框架。

1.2 MyBatis中的主要设计模式

MyBatis中使用的设计模式包括:

  1. 构建者模式(Builder Pattern) :SqlSessionFactoryBuilder、CacheBuilder、ParameterExpression等
  2. 工厂模式(Factory Pattern) :SqlSessionFactory、MapperProxyFactory、ObjectFactory、DataSourceFactory等
  3. 代理模式(Proxy Pattern) :MapperProxy、Plugin、ConnectionLogger、PreparedStatementLogger等
  4. 组合模式(Composite Pattern) :SqlNode、DynamicContext等
  5. 模板方法模式(Template Method Pattern) :BaseExecutor、SimpleExecutor、BatchExecutor等
  6. 适配器模式(Adapter Pattern) :Log接口及其适配器
  7. 装饰器模式(Decorator Pattern) :CachingExecutor、Executor的包装
  8. 策略模式(Strategy Pattern) :RoutingStatementHandler、ResultSetHandler等
  9. 迭代器模式(Iterator Pattern) :PropertyTokenizer、DefaultCursor等
  10. 责任链模式(Chain of Responsibility) :Interceptor链、Plugin链

本文将重点讲解构建者模式、工厂模式和代理模式在MyBatis中的应用。

二、构建者模式(Builder Pattern)

构建者模式是一种创建型设计模式,它允许你分步骤创建复杂对象。该模式使你可以使用相同的创建代码生成不同类型和形式的对象。

2.1 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder是MyBatis中最典型的构建者模式应用。它负责从XML配置文件或Configuration对象构建SqlSessionFactory。

2.1.1 基本用法

ini 复制代码
// 从XML文件构建
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

// 从Configuration对象构建
Configuration config = new Configuration();
config.addMapper(UserMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);

2.1.2 源码分析

typescript 复制代码
public class SqlSessionFactoryBuilder {

    // 从InputStream构建
    public SqlSessionFactory build(InputStream inputStream) {
        return build(inputStream, null, null);
    }

    public SqlSessionFactory build(InputStream inputStream, String environment) {
        return build(inputStream, environment, null);
    }

    public SqlSessionFactory build(InputStream inputStream, Properties properties) {
        return build(inputStream, null, properties);
    }

    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        try {
            // 1. 解析XML配置文件,创建XMLConfigBuilder
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            // 2. 解析配置并构建Configuration对象
            return build(parser.parse());
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", e);
        } finally {
            ErrorContext.instance().reset();
            try {
                inputStream.close();
            } catch (IOException e) {
                // ignore
            }
        }
    }

    // 从Configuration构建
    public SqlSessionFactory build(Configuration config) {
        // 3. 创建DefaultSqlSessionFactory
        return new DefaultSqlSessionFactory(config);
    }

    // 从Reader构建
    public SqlSessionFactory build(Reader reader) {
        return build(reader, null, null);
    }

    public SqlSessionFactory build(Reader reader, String environment) {
        return build(reader, environment, null);
    }

    public SqlSessionFactory build(Reader reader, Properties properties) {
        return build(reader, null, properties);
    }

    public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
            return build(parser.parse());
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", e);
        } finally {
            ErrorContext.instance().reset();
            try {
                reader.close();
            } catch (IOException e) {
                // ignore
            }
        }
    }
}

2.1.3 构建过程分析

SqlSessionFactoryBuilder的构建过程可以分为以下几个步骤:

  1. 加载配置文件:从InputStream或Reader加载XML配置文件
  2. 创建解析器:创建XMLConfigBuilder解析XML配置
  3. 解析配置:解析XML配置文件,构建Configuration对象
  4. 创建工厂:使用Configuration对象创建SqlSessionFactory

2.2 XMLConfigBuilder

XMLConfigBuilder是实际的构建者,负责解析XML配置文件并构建Configuration对象。

scala 复制代码
public class XMLConfigBuilder extends BaseBuilder {

    private boolean parsed;
    private final XPathParser parser;
    private String environment;

    public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
        this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
    }

    // 解析配置
    public Configuration parse() {
        if (parsed) {
            throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        }
        parsed = true;
        // 解析configuration节点
        parseConfiguration(parser.evalNode("/configuration"));
        return configuration;
    }

    private void parseConfiguration(XNode root) {
        try {
            // 解析各个配置项
            propertiesElement(root.evalNode("properties"));
            typeAliasesElement(root.evalNode("typeAliases"));
            pluginsElement(root.evalNode("plugins"));
            objectFactoryElement(root.evalNode("objectFactory"));
            objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
            reflectionFactoryElement(root.evalNode("reflectionFactory"));
            settingsElement(root.evalNode("settings"));
            environmentsElement(root.evalNode("environments"));
            databaseIdProviderElement(root.evalNode("databaseIdProvider"));
            typeHandlerElement(root.evalNode("typeHandlers"));
            mapperElement(root.evalNode("mappers"));
        } catch (Exception e) {
            throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
        }
    }
}

2.3 构建者模式的优势

  1. 分步构建:将复杂对象的构建过程分解为多个步骤
  2. 代码复用:相同的构建代码可以创建不同的对象
  3. 封装复杂度:隐藏对象创建的复杂细节
  4. 灵活配置:支持多种不同的配置方式

2.4 其他构建者模式应用

除了SqlSessionFactoryBuilder,MyBatis中还有其他构建者模式的应用:

2.4.1 CacheBuilder

typescript 复制代码
public class CacheBuilder {
    private final String id;
    private Class<? extends Cache> implementation;
    private List<Class<? extends Cache>> decorators;
    private Integer size;
    private Long clearInterval;
    private boolean readWrite;
    private Properties properties;

    public Cache build() {
        // 设置默认实现
        setDefaultImplementations();

        // 创建缓存
        Cache cache = newBaseCacheInstance(implementation, id);
        setCacheProperties(cache);

        // 应用装饰器
        for (Class<? extends Cache> decorator : decorators) {
            cache = newCacheDecoratorInstance(decorator, cache);
            setCacheProperties(cache);
        }

        return cache;
    }
}

2.4.2 ParameterExpression

typescript 复制代码
public class ParameterExpression implements Iterator<ParameterExpression> {
    // 构建者模式用于解析参数表达式
    public ParameterExpression(String expression) {
        parseExpression(expression);
    }

    private void parseExpression(String expression) {
        // 解析属性表达式
    }
}

三、工厂模式(Factory Pattern)

工厂模式是一种创建型设计模式,它提供了创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

3.1 SqlSessionFactory

SqlSessionFactory是MyBatis中最核心的工厂接口,负责创建SqlSession对象。

3.1.1 接口定义

scss 复制代码
public interface SqlSessionFactory {

    // 创建SqlSession的各种方法
    SqlSession openSession();
    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();
}

3.1.2 DefaultSqlSessionFactory

java 复制代码
public class DefaultSqlSessionFactory implements SqlSessionFactory {

    private final Configuration configuration;

    public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public SqlSession openSession() {
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
    }

    @Override
    public SqlSession openSession(boolean autoCommit) {
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
    }

    @Override
    public SqlSession openSession(ExecutorType execType) {
        return openSessionFromDataSource(execType, null, false);
    }

    @Override
    public SqlSession openSession(TransactionIsolationLevel level) {
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
    }

    private SqlSession openSessionFromDataSource(ExecutorType execType,
                                                  TransactionIsolationLevel level,
                                                  boolean autoCommit) {
        Transaction tx = null;
        try {
            // 1. 获取环境配置
            Environment environment = configuration.getEnvironment();
            // 2. 获取事务工厂
            TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            // 3. 创建事务对象
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            // 4. 创建执行器
            Executor executor = configuration.newExecutor(tx, execType);
            // 5. 创建SqlSession
            return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            closeTransaction(tx);
            throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }
}

3.2 MapperProxyFactory

MapperProxyFactory负责创建Mapper接口的代理对象。

3.2.1 源码分析

typescript 复制代码
public class MapperProxyFactory<T> {

    private final Class<T> mapperInterface;
    private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();

    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) {
        // 使用JDK动态代理创建代理对象
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(),
            new Class[] { mapperInterface },
            mapperProxy);
    }

    public T newInstance(SqlSession sqlSession) {
        final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
        return newInstance(mapperProxy);
    }
}

3.2.2 使用示例

typescript 复制代码
// MapperRegistry中注册Mapper
public <T> void addMapper(Class<T> type) {
    if (type.isInterface()) {
        if (hasMapper(type)) {
            throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
        }
        boolean loadCompleted = false;
        try {
            // 创建MapperProxyFactory并注册
            knownMappers.put(type, new MapperProxyFactory<>(type));
            // 解析注解
            MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
            parser.parse();
            loadCompleted = true;
        } finally {
            if (!loadCompleted) {
                knownMappers.remove(type);
            }
        }
    }
}

// 获取Mapper实例
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
        throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
        // 通过工厂创建Mapper代理对象
        return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
        throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
}

3.3 ObjectFactory

ObjectFactory是MyBatis的对象工厂,负责创建对象实例。

3.3.1 接口定义

swift 复制代码
public interface ObjectFactory {

    // 创建对象
    <T> T create(Class<T> type);

    // 有参构造创建对象
    <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);

    // 判断是否是集合类型
    <T> boolean isCollection(Class<T> type);
}

3.3.2 DefaultObjectFactory

typescript 复制代码
public class DefaultObjectFactory implements ObjectFactory {

    @Override
    public <T> T create(Class<T> type) {
        return create(type, null, null);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        // 1. 解析集合类型
        Class<?> classToCreate = resolveInterface(type);
        // 2. 使用构造器创建实例
        return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
    }

    private  <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes,
                                     List<Object> constructorArgs) {
        try {
            Constructor<T> constructor;
            // 有参构造
            if (constructorArgTypes == null || constructorArgs == null) {
                constructor = type.getDeclaredConstructor();
                if (!constructor.isAccessible()) {
                    constructor.setAccessible(true);
                }
                return constructor.newInstance();
            } else {
                // 查找匹配的构造器
                constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));
                if (!constructor.isAccessible()) {
                    constructor.setAccessible(true);
                }
                return constructor.newInstance(constructorArgs.toArray(new Object[0]));
            }
        } catch (Exception e) {
            // 处理异常
        }
    }

    @Override
    public <T> boolean isCollection(Class<T> type) {
        return Collection.class.isAssignableFrom(type);
    }
}

3.4 工厂模式的优势

  1. 解耦:调用者不需要知道对象创建的细节
  2. 扩展性:新增产品类时不需要修改现有代码
  3. 复用性:工厂类可以被多个客户端复用
  4. 封装性:封装了对象创建的复杂逻辑

四、代理模式(Proxy Pattern)

代理模式是一种结构型设计模式,它允许你提供对象的替代品或占位符。代理控制着对原对象的访问,并允许在将请求提交给对象前后进行一些处理。

4.1 MapperProxy

MapperProxy是MyBatis中最核心的代理模式应用,它为Mapper接口创建代理对象,拦截方法调用并执行相应的SQL操作。

4.1.1 源码分析

kotlin 复制代码
public class MapperProxy<T> implements InvocationHandler {

    private final SqlSession sqlSession;
    private final Class<T> mapperInterface;
    private final Map<Method, MapperMethod> methodCache;

    public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
        this.methodCache = methodCache;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 1. 如果是Object类的方法,直接执行
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }

        // 2. 获取MapperMethod
        final MapperMethod mapperMethod = cachedMapperMethod(method);

        // 3. 执行Mapper方法
        return mapperMethod.execute(sqlSession, args);
    }

    private MapperMethod cachedMapperMethod(Method method) {
        return methodCache.computeIfAbsent(method,
            k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
    }
}

4.1.2 MapperMethod

ini 复制代码
public class MapperMethod {

    private final SqlCommand command;
    private final MethodSignature method;

    public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
        this.command = new SqlCommand(config, mapperInterface, method);
        this.method = new MethodSignature(config, mapperInterface, method);
    }

    public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        switch (command.getType()) {
            case INSERT: {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.insert(command.getName(), param));
                break;
            }
            case UPDATE: {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.update(command.getName(), param));
                break;
            }
            case DELETE: {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.delete(command.getName(), param));
                break;
            }
            case SELECT:
                if (method.returnsVoid() && method.hasResultHandler()) {
                    executeWithResultHandler(sqlSession, args);
                    result = null;
                } else if (method.returnsMany()) {
                    result = executeForMany(sqlSession, args);
                } else if (method.returnsMap()) {
                    result = executeForMap(sqlSession, args);
                } else if (method.returnsCursor()) {
                    result = executeForCursor(sqlSession, args);
                } else {
                    Object param = method.convertArgsToSqlCommandParam(args);
                    result = sqlSession.selectOne(command.getName(), param);
                    if (method.returnsOptional()
                        && (result == null || !method.getReturnType().equals(result.getClass()))) {
                        result = Optional.ofNullable(result);
                    }
                }
                break;
            case FLUSH:
                result = sqlSession.flushStatements();
                break;
            default:
                throw new BindingException("Unknown execution method for: " + command.getName());
        }
        if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
            throw new BindingException("Mapper method '" + command.getName()
                + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
        }
        return result;
    }
}

4.2 Plugin拦截器

Plugin是MyBatis的插件机制的核心,它通过动态代理实现对目标对象的拦截。

4.2.1 Interceptor接口

typescript 复制代码
public interface Interceptor {

    // 拦截方法
    Object intercept(Invocation invocation) throws Throwable;

    // 创建代理对象
    default Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    // 设置属性
    default void setProperties(Properties properties) {
        // NOP
    }
}

4.2.2 Plugin类

typescript 复制代码
public class Plugin implements InvocationHandler {

    private final Object target;
    private final Interceptor interceptor;
    private final Map<Class<?>, Set<Method>> signatureMap;

    private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
        this.target = target;
        this.interceptor = interceptor;
        this.signatureMap = signatureMap;
    }

    public static Object wrap(Object target, Interceptor interceptor) {
        // 1. 获取拦截的类和方法签名
        Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
        Class<?> type = target.getClass();

        // 2. 获取所有需要拦截的接口
        Class<?>[] interfaces = getAllInterfaces(type, signatureMap);

        // 3. 如果有需要拦截的接口,创建代理对象
        if (interfaces.length > 0) {
            return Proxy.newProxyInstance(
                type.getClassLoader(),
                interfaces,
                new Plugin(target, interceptor, signatureMap));
        }
        return target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            // 4. 检查当前方法是否需要被拦截
            Set<Method> methods = signatureMap.get(method.getDeclaringClass());
            if (methods != null && methods.contains(method)) {
                // 5. 调用拦截器的intercept方法
                return interceptor.intercept(new Invocation(target, method, args));
            }
            // 6. 不需要拦截,直接调用目标方法
            return method.invoke(target, args);
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error: " + e, e);
        }
    }

    private static Map<Class<?>, Set<Method>> getSignatureMap(Interceptor interceptor) {
        // 获取@Intercepts注解
        Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
        if (interceptsAnnotation == null) {
            throw new PluginException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName());
        }

        Signature[] sigs = interceptsAnnotation.value();
        Map<Class<?>, Set<Method>> signatureMap = new HashMap<>();
        for (Signature sig : sigs) {
            Set<Method> methods = signatureMap.computeIfAbsent(sig.type(), k -> new HashSet<>());
            try {
                Method method = sig.type().getMethod(sig.method(), sig.args());
                methods.add(method);
            } catch (NoSuchMethodException e) {
                throw new PluginException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e, e);
            }
        }
        return signatureMap;
    }

    private static Class<?>[] getAllInterfaces(Class<?> type, Map<Class<?>, Set<Method>> signatureMap) {
        Set<Class<?>> interfaces = new HashSet<>();
        while (type != null) {
            for (Class<?> c : type.getInterfaces()) {
                if (signatureMap.containsKey(c)) {
                    interfaces.add(c);
                }
            }
            type = type.getSuperclass();
        }
        return interfaces.toArray(new Class<?>[0]);
    }
}

4.2.3 插件使用示例

less 复制代码
@Intercepts({
    @Signature(type = Executor.class,
               method = "update",
               args = {MappedStatement.class, Object.class}),
    @Signature(type = Executor.class,
               method = "query",
               args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class MyPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 前置处理
        System.out.println("Before: " + invocation.getMethod().getName());

        // 执行目标方法
        Object result = invocation.proceed();

        // 后置处理
        System.out.println("After: " + invocation.getMethod().getName());

        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 读取配置
    }
}

4.3 代理模式的优势

  1. 职责清晰:将日志、事务等横切关注点与业务逻辑分离
  2. 灵活性:可以在不修改原始对象的情况下增加功能
  3. 可扩展性:通过插件机制轻松扩展框架功能
  4. 解耦:调用者不需要知道代理的存在

五、设计模式的协同应用

在MyBatis中,多种设计模式往往协同工作,共同完成复杂的功能。

5.1 创建SqlSession的完整流程

创建SqlSession的过程涉及多个设计模式的协同:

  1. 构建者模式:SqlSessionFactoryBuilder构建Configuration
  2. 工厂模式:SqlSessionFactory创建SqlSession
  3. 代理模式:MapperProxy创建Mapper代理对象
ini 复制代码
// 1. 构建者模式:构建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
    .build(Resources.getResourceAsStream("mybatis-config.xml"));

// 2. 工厂模式:创建SqlSession
SqlSession session = factory.openSession();

// 3. 代理模式:获取Mapper代理对象
UserMapper mapper = session.getMapper(UserMapper.class);

5.2 执行SQL的完整流程

执行SQL的过程也涉及多个设计模式的协同:

  1. 代理模式:MapperProxy拦截方法调用
  2. 工厂模式:SqlSession创建Statement
  3. 模板方法模式:BaseExecutor定义执行流程
  4. 策略模式:不同的Executor使用不同的执行策略

六、最佳实践

6.1 使用构建者模式

当你需要创建复杂对象时,可以考虑使用构建者模式:

typescript 复制代码
public class ComplexObjectBuilder {
    private ComplexObject object = new ComplexObject();

    public ComplexObjectBuilder withProperty1(String value) {
        object.setProperty1(value);
        return this;
    }

    public ComplexObjectBuilder withProperty2(int value) {
        object.setProperty2(value);
        return this;
    }

    public ComplexObject build() {
        return object;
    }
}

// 使用
ComplexObject obj = new ComplexObjectBuilder()
    .withProperty1("value1")
    .withProperty2(100)
    .build();

6.2 使用工厂模式

当对象的创建逻辑复杂或需要根据配置创建不同实现时,使用工厂模式:

typescript 复制代码
public interface ServiceFactory {
    Service createService();
}

public class ServiceFactoryA implements ServiceFactory {
    @Override
    public Service createService() {
        return new ServiceA();
    }
}

public class ServiceFactoryB implements ServiceFactory {
    @Override
    public Service createService() {
        return new ServiceB();
    }
}

6.3 使用代理模式

当你需要在不修改原始对象的情况下添加功能时,使用代理模式:

typescript 复制代码
public class ServiceProxy implements InvocationHandler {
    private Object target;

    public ServiceProxy(Object target) {
        this.target = target;
    }

    public static <T> T createProxy(T target) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new ServiceProxy(target));
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置处理
        System.out.println("Before: " + method.getName());

        // 执行目标方法
        Object result = method.invoke(target, args);

        // 后置处理
        System.out.println("After: " + method.getName());

        return result;
    }
}

七、总结

MyBatis作为一款优秀的持久层框架,其代码中大量运用了经典的设计模式。这些设计模式的应用,使得MyBatis具有良好的架构设计和可扩展性。

这些设计模式不是孤立存在的,而是相互配合,共同构建了MyBatis强大的功能体系。深入理解这些设计模式,不仅有助于我们更好地使用MyBatis,也能为我们自己的架构设计提供参考和借鉴。

相关推荐
while(1){yan}9 小时前
Spring事务
java·数据库·spring boot·后端·java-ee·mybatis
*.✧屠苏隐遥(ノ◕ヮ◕)ノ*.✧10 小时前
《苍穹外卖》- day01 开发环境搭建
spring boot·后端·spring·maven·intellij-idea·mybatis
曹轲恒10 小时前
@PropertySource、@ImportResource、@Bean
java·spring boot·mybatis
程序员侠客行20 小时前
Spring集成Mybatis原理详解
java·后端·spring·架构·mybatis
tqs_123451 天前
@transactional事务失效场景
java·数据库·mybatis
小北方城市网1 天前
Spring Cloud Gateway实战:路由、限流、熔断与鉴权全解析
java·spring boot·后端·spring·mybatis
huohuopro1 天前
Mybatis的七种传参方式
java·开发语言·mybatis
sunnyday04261 天前
Spring Boot 自定义 Starter 实战:从创建到使用的完整指南
spring boot·后端·mybatis
小北方城市网1 天前
Redis 分布式锁与缓存三大问题解决方案
spring boot·redis·分布式·后端·缓存·wpf·mybatis
Dontla2 天前
Mybatis Introduction (Java ORM Framework)
java·开发语言·mybatis