乐于分享
好东西不私藏

MyBatis 源码深度拆解(三):Mapper 接口动态代理底层原理

MyBatis 源码深度拆解(三):Mapper 接口动态代理底层原理

写在最前面 版本说明本文主要基于 MyBatis 3.5.10 和 mybatis-spring 3.0.3 源码进行分析。不同小版本可能在缓存实现、default 方法处理等方面存在差异,建议读者以自己实际使用的版本源码为准。

一、从一道面试题说起

很多初学者都会问:我明明只定义了一个UserMapper接口,并没有写实现类,为什么 MyBatis 能帮我执行 SQL?

答案:JDK 动态代理。MyBatis 在运行时为你的接口生成了一个代理对象,所有的方法调用都会被这个代理对象拦截,然后转发给SqlSession去执行。

今天我们就从源码角度,把代理对象的创建过程调用过程完整拆解一遍。

二、代理对象的创建时机

2.1 入口:session.getMapper(UserMapper.class)

我们通常这样获取 Mapper:

UserMapper mapper = session.getMapper(UserMapper.class);

这个 session 实际是 DefaultSqlSession,我们跟进去:

@Overridepublic <T> T getMapper(Class<T> type) {    return configuration.getMapper(typethis);}

继续:

// Configurationpublic <T> T getMapper(Class<T> typeSqlSession sqlSession) {    return mapperRegistry.getMapper(type, sqlSession);}

mapperRegistryMapperRegistry类型,它是Configuration中专门管理 Mapper 接口与代理工厂的注册表。

2.2 MapperRegistry.getMapper()

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

关键点

  • knownMappers是一个Map<Class<?>, MapperProxyFactory<?>>,在解析配置文件或包扫描时就已经填充好了。
  • 每个 Mapper 接口对应一个MapperProxyFactory,专门用来生成该接口的代理对象。

2.3 MapperProxyFactory.newInstance()

public T newInstance(SqlSession sqlSession) {    // 创建 MapperProxy,它实现了 InvocationHandler    final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);    return newInstance(mapperProxy);}protected T newInstance(MapperProxy<T> mapperProxy) {    // 使用 JDK 动态代理生成代理对象    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(),                                       new Class[] { mapperInterface },                                       mapperProxy);}

到这里,代理对象就诞生了。

核心三要素

  • 类加载器mapperInterface.getClassLoader()
  • 要代理的接口数组new Class[] { mapperInterface }
  • InvocationHandlermapperProxy,当代理对象的方法被调用时,会进入它的 invoke 方法。

三、代理对象的方法调用链路

当调用userMapper.selectById(1)时,实际上进入的是MapperProxy.invoke()

3.1 MapperProxy.invoke()

@Overridepublic Object invoke(Object proxy, Method methodObject[] argsthrowsThrowable{    try {        // 如果是 Object 类的方法(如 toString、hashCode),直接调用,不拦截        if (Object.class.equals(method.getDeclaringClass())) {            return method.invoke(this, args);        }        // 缓存或新建 MapperMethod,然后执行        return cachedInvoker(method).invoke(proxy, method, args, sqlSession);    } catch (Throwable t) {        throw ExceptionUtil.unwrapThrowable(t);    }}

这里出现了 MapperMethod,它是真正干活的类。

3.2cachedInvoker(method)MapperMethod

cachedInvoker会从methodCache(一个ConcurrentHashMap<Method, MapperMethodInvoker>)中获取或创建MapperMethodInvokerMapperMethodInvoker是 MyBatis 内部定义的函数式接口,有两个实现类:

  • PlainMethodInvoker:内部持有MapperMethod对象,负责普通接口方法的 SQL 执行;
  • DefaultMethodInvoker:直接调用接口中的default方法(Java 8+)。

每次方法调用时,methodCache 缓存的是 MapperMethodInvoker,而 MapperMethod 只是 PlainMethodInvoker 的一个成员变量。

private MapperMethodInvoker cachedInvoker(Method methodthrowsThrowable{    try {      return MapUtil.computeIfAbsent(methodCache, methodm -> {        if (!m.isDefault()) {          return new PlainMethodInvoker(new MapperMethod(mapperInterface, methodsqlSession.getConfiguration()));        }        try {          if (privateLookupInMethod == null) {            return new DefaultMethodInvoker(getMethodHandleJava8(method));          }          return new DefaultMethodInvoker(getMethodHandleJava9(method));        } catch (IllegalAccessException | InstantiationException | InvocationTargetException            | NoSuchMethodException e) {          throw new RuntimeException(e);        }      });    } catch (RuntimeException re) {      Throwable cause = re.getCause();      throw cause == null ? re : cause;    }  }

MapperMethod构造时会解析:

  • 方法名(对应 Mapper XML 中的 id)
  • 方法的返回类型(是单对象还是集合?)
  • 方法的参数信息(是否使用@Param等)

MapperMethod 中有两个核心字段:

public classMapperMethod{    private final SqlCommand command;   // 封装 SQL 的类型(SELECT/INSERT/UPDATE/DELETE)和 MappedStatement 的 id    private final MethodSignature method; // 封装方法的签名信息(返回类型、参数等)}

3.3MapperMethod.execute()

PlainMethodInvoker.invoke()

最终会调用mapperMethod.execute(sqlSession, args)

public Object execute(SqlSession sqlSession, Object[] args) {    Object result;    switch (command.getType()) {        case INSERT:            // 处理 insert            break;        case UPDATE:            // 处理 update            break;        case DELETE:            // 处理 delete            break;        case SELECT:            // 根据返回类型,调用 sqlSession 的不同方法            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);            }            break;        case FLUSH:            result = sqlSession.flushStatements();            break;        default:            throw new BindingException("Unknown execution method...");    }    return result;}

最终,我们看到了我们熟悉的方法:sqlSession.selectOne() 或 selectList(),后面的流程就回到了第一篇中讲过的 Executor → StatementHandler → JDBC。

四、@MapperScan层注册流程(Spring 集成)

4.1 整体设计理念:延迟扫描

@MapperScan 的设计理念是 延迟扫描 + 职责分离

角色

实现类

核心职责

触发者

@MapperScan 注解

声明扫描范围,通过@Import导入 Registrar

定义注册者

MapperScannerRegistrar

注册MapperScannerConfigurer

的 BeanDefinition

扫描执行者

MapperScannerConfigurer

实现BeanDefinitionRegistryPostProcessor

,在 Spring 生命周期中触发扫描

核心扫描器

ClassPathMapperScanner

执行真正的包扫描和 BeanDefinition 转换

4.2 阶段一:MapperScannerRegistrar — 注册扫描器定义

@MapperScan 注解通过 @Import 导入了 MapperScannerRegistrar

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Import(MapperScannerRegistrar.class)  // 关键:导入了一个 Registrarpublic @interface MapperScan {    String[] value() default {};    String[] basePackages() default {};    // ...}

MapperScannerRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,Spring 启动时会调用其 registerBeanDefinitions 方法:

@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,                                     BeanDefinitionRegistry registry) {    // 1. 获取 @MapperScan 注解的所有属性    AnnotationAttributes mapperScanAttrs = AnnotationAttributes.fromMap(        importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));    if (mapperScanAttrs != null) {        // 2. 调用重载方法,传入生成的基名        this.registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry,                                      generateBaseBeanName(importingClassMetadata, 0));    }}private void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,                                     AnnotationAttributes mapperScanAttrs,                                     BeanDefinitionRegistry registry, String beanName) {    // 3. 创建 MapperScannerConfigurer 的 BeanDefinitionBuilder    BeanDefinitionBuilder builder = BeanDefinitionBuilder        .genericBeanDefinition(MapperScannerConfigurer.class);    // 4. 设置 basePackage(扫描路径)    builder.addPropertyValue("basePackage"        StringUtils.collectionToCommaDelimitedString(basePackages));    // 5. 其他属性设置(sqlSessionFactoryBeanName、annotationClass 等)    // 6. 注册到 Spring 容器,此时扫描尚未执行    registry.registerBeanDefinition(beanName, builder.getBeanDefinition());}

核心要点

  • MapperScannerRegistrar只注册 MapperScannerConfigurer 的 BeanDefinition,不执行扫描
  • 扫描动作被推迟到 Spring 后续的生命周期中执行

4.3 阶段二:MapperScannerConfigurer — 触发扫描

MapperScannerConfigurer 实现了 BeanDefinitionRegistryPostProcessor 接口,这是 Spring 提供的核心扩展点,允许在 Bean 实例化之前修改或新增 BeanDefinition。

Spring 在 refresh() 容器的 invokeBeanDefinitionRegistryPostProcessors 阶段,会回调 postProcessBeanDefinitionRegistry 方法

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {    // 1. 处理占位符(如 ${basePackage})    if (this.processPropertyPlaceHolders) {        processPropertyPlaceHolders();    }    // 2. 创建 ClassPathMapperScanner    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);    // 3. 设置各项属性    scanner.setAddToConfig(this.addToConfig);    scanner.setAnnotationClass(this.annotationClass);    scanner.setMarkerInterface(this.markerInterface);    scanner.setSqlSessionFactory(this.sqlSessionFactory);    scanner.setSqlSessionTemplate(this.sqlSessionTemplate);    scanner.setResourceLoader(this.applicationContext);    scanner.setBeanNameGenerator(this.nameGenerator);    // 4. 注册过滤器(决定哪些接口被扫描)    scanner.registerFilters();    // 5. 执行扫描(核心动作)    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage,         ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));}

执行时机:此方法在容器解析完所有 XML 和注解配置之后、任何 Bean 实例化之前执行,是 Spring 提供的最后添加 BeanDefinition 的地方

4.4 阶段三:ClassPathMapperScanner — 扫描与 BeanDefinition 转换

ClassPathMapperScanner 继承自 Spring 的 ClassPathBeanDefinitionScanner,重写了 doScan 方法:

// ClassPathMapperScanner (mybatis-spring 3.0.3)public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {    private Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class;    @Override    public Set<BeanDefinitionHolderdoScan(String... basePackages) {        // 1. 调用父类进行标准组件扫描,得到原始 BeanDefinition(beanClass = 接口本身)        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);        if (!beanDefinitions.isEmpty()) {            // 2. 对扫描到的 BeanDefinition 进行二次处理(关键步骤)            processBeanDefinitions(beanDefinitions);        }        return beanDefinitions;    }    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {        for (BeanDefinitionHolder holder : beanDefinitions) {            BeanDefinition definition = holder.getBeanDefinition();            // 3. 修改 beanClass:将接口类型改为 MapperFactoryBean            definition.setBeanClass(this.mapperFactoryBeanClass);            // 4. 添加构造参数:原始 Mapper 接口类型            definition.getConstructorArgumentValues()                .addGenericArgumentValue(definition.getBeanClassName());            // 5. 添加属性:sqlSessionFactory 或 sqlSessionTemplate            if (this.sqlSessionFactory != null) {                definition.getPropertyValues().add("sqlSessionFactory"this.sqlSessionFactory);            }            if (this.sqlSessionTemplate != null) {                definition.getPropertyValues().add("sqlSessionTemplate"this.sqlSessionTemplate);            }        }    }}

关键转换

转换前

转换后

beanName =userMapper

beanName =userMapper

(不变)

beanClass =com.example.mapper.UserMapper(接口)

beanClass =MapperFactoryBean

无构造参数

构造参数 =UserMapper.class

4.5 阶段四:MapperFactoryBean — 生成代理对象

经过上述转换,Spring 容器中每个 Mapper 接口都对应一个MapperFactoryBean的 BeanDefinition。

MapperFactoryBean 实现了 FactoryBean 接口,Spring 实例化时会调用 getObject() 方法获取真正的 Mapper 代理对象:

// MapperFactoryBean (mybatis-spring 3.0.3)public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {    private Class<T> mapperInterface;    public MapperFactoryBean(Class<T> mapperInterface) {        this.mapperInterface = mapperInterface;    }    @Override    public T getObject() throws Exception {        // 通过 SqlSession 获取 Mapper 代理对象        return getSqlSession().getMapper(this.mapperInterface);    }}

getSqlSession().getMapper()的调用链最终进入 MyBatis 核心:

SqlSessionTemplate.getMapper()    → Configuration.getMapper()        → MapperRegistry.getMapper()            → MapperProxyFactory.newInstance()                → Proxy.newProxyInstance() → 生成 MapperProxy

最终,Spring 容器中存入的是 MapperProxy 动态代理对象,这就是为什么我们可以直接用 @Autowired 注入一个接口的原因。

4.7 完整调用链总览

启动类 @MapperScan("com.example.mapper")    ↓@Import(MapperScannerRegistrar.class)    ↓MapperScannerRegistrar.registerBeanDefinitions()    → 注册 MapperScannerConfigurer 的 BeanDefinition    ↓Spring refresh() → invokeBeanDefinitionRegistryPostProcessors    ↓MapperScannerConfigurer.postProcessBeanDefinitionRegistry()    → 创建 ClassPathMapperScanner    → 调用 scanner.scan(basePackages)        ↓    ClassPathMapperScanner.doScan()        → super.doScan() → 父类扫描包,发现 Mapper 接口        → processBeanDefinitions()            → 修改 BeanDefinition:beanClass = MapperFactoryBean            → 添加构造参数:原始 Mapper 接口类型        ↓    MapperFactoryBean.getObject()        → sqlSession.getMapper(mapperInterface)            → MapperRegistry.getMapper()                → MapperProxyFactory.newInstance()                    → JDK 动态代理 → MapperProxy        ↓Spring 容器注入 MapperProxy 代理对象

五、面试高频题

Q1:MyBatis 的 Mapper 接口为什么不需要实现类?

A:因为 MyBatis 使用了 JDK 动态代理,在运行时为接口生成了一个代理对象。当调用接口方法时,会被MapperProxy.invoke()拦截,然后根据方法名找到对应的MappedStatement,最终调用SqlSession执行 SQL。

Q2:MapperProxy中为什么要缓存MapperMethod

AMapperMethod的构造过程需要解析方法的返回值类型、参数信息等,这些信息是固定的。缓存可以避免每次方法调用都重复解析,提高性能。

Q3:@MapperScan的原理是什么?

A@MapperScan 底层通过 @Import(MapperScannerRegistrar.class) 导入了一个 ImportBeanDefinitionRegistrar。Spring 启动时,MapperScannerRegistrar 会向容器注册一个 MapperScannerConfigurer 的 BeanDefinition。MapperScannerConfigurer 实现了 BeanDefinitionRegistryPostProcessor,所以在 Spring 的 refresh() 过程中,它的 postProcessBeanDefinitionRegistry 方法会被调用。在这个方法里,会创建一个 ClassPathMapperScanner,执行 doScan 扫描指定包下的所有 Mapper 接口,然后将每个接口的 BeanDefinition 的 beanClass 修改为 MapperFactoryBean,并将原始接口类型作为构造参数传入。最终,Spring 实例化 MapperFactoryBean 时,会调用其 getObject() 方法,通过 SqlSession.getMapper() 生成真正的 Mapper 动态代理对象(即 MapperProxy)并注入容器。

Q4:MapperFactoryBeanMapperProxyFactory是什么关系?

A

  • MapperProxyFactory是 MyBatis 内部用来创建代理对象的工厂,与 Spring 无关。
  • MapperFactoryBean是 Spring 集成中的适配器,它实现了FactoryBean,内部持有SqlSession,并调用sqlSession.getMapper()来获取代理对象,而sqlSession.getMapper()最终会调用MapperProxyFactory创建代理。

六、下篇预告

第 4 篇我们将深入SqlSession体系,拆解DefaultSqlSessionSqlSessionFactory的构建流程,以及SqlSession的四大核心对象的初始化时机。

如果觉得有帮助,欢迎点赞、在看、转发支持!

系列持续更新,关注不走丢 👇

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-06-14 21:52:02 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/752547.html
  2. 运行时间 : 0.150774s [ 吞吐率:6.63req/s ] 内存消耗:4,743.72kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=5ffdf8b47c261a56e06e43fa427fafcc
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.001571s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001294s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000497s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000644s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000889s ]
  6. SELECT * FROM `set` [ RunTime:0.000444s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000978s ]
  8. SELECT * FROM `article` WHERE `id` = 752547 LIMIT 1 [ RunTime:0.002435s ]
  9. UPDATE `article` SET `lasttime` = 1781445123 WHERE `id` = 752547 [ RunTime:0.011703s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000299s ]
  11. SELECT * FROM `article` WHERE `id` < 752547 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000539s ]
  12. SELECT * FROM `article` WHERE `id` > 752547 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000488s ]
  13. SELECT * FROM `article` WHERE `id` < 752547 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.003033s ]
  14. SELECT * FROM `article` WHERE `id` < 752547 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.002450s ]
  15. SELECT * FROM `article` WHERE `id` < 752547 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.008300s ]
0.152607s