当前位置:首页>java>别在业务代码里硬编码!用ApplicationListener搞定系统事件,解耦神器!

别在业务代码里硬编码!用ApplicationListener搞定系统事件,解耦神器!

  • 2026-01-31 19:20:14
别在业务代码里硬编码!用ApplicationListener搞定系统事件,解耦神器!

你是否还在业务代码里写硬编码的系统初始化逻辑?上周我重构了一个500行的初始化方法,用ApplicationListener把它拆成了5个独立的监听器,系统可维护性瞬间提升几个档次...

01、一个典型的系统初始化烂摊子

上周团队让我帮忙review一个用户中心的代码,我看到这样一个服务类:

@Servicepublic class UserSystemInitializer {    @Autowired    private CacheService cacheService;    @Autowired    private MessageQueueService mqService;    @Autowired    private ScheduledExecutorService scheduler;    @Autowired    private ExternalServiceClient externalClient;    @PostConstruct    public void initEverything() {        log.info("开始初始化用户中心系统...");        // 1. 加载缓存        try {            cacheService.loadAllUserCache();        } catch (Exception e) {            log.error("缓存加载失败", e);        }        // 2. 启动消息监听        try {            mqService.startListenUserEvents();        } catch (Exception e) {            log.error("消息监听启动失败", e);        }        // 3. 启动定时任务        try {            scheduler.scheduleAtFixedRate(this::syncExternalData, 0, 5, TimeUnit.MINUTES);        } catch (Exception e) {            log.error("定时任务启动失败", e);        }        // 4. 建立外部服务连接        try {            externalClient.preheatConnection();        } catch (Exception e) {            log.error("外部服务连接预热失败", e);        }        // 5. 发送系统启动通知        try {            notifySystemStarted();        } catch (Exception e) {            log.error("系统启动通知发送失败", e);        }        log.info("用户中心系统初始化完成");    }    // 后面还有十几个私有方法...}

看到这段代码,我仿佛看到了三年前的自己。这种"一锅炖"的初始化方式存在几个致命问题:

  1. 1. 职责不清:一个方法做多件事,违反了单一职责原则
  2. 2. 异常处理混乱:某个步骤失败不影响其他步骤?但日志里根本看不出哪里出了问题
  3. 3. 难以扩展:想要新增一个初始化步骤,得在这个500行的方法里找地方插入
  4. 4. 无法复用:其他模块想要类似的初始化逻辑,只能复制粘贴

02、Spring事件监听机制:观察者模式的完美实践

Spring的事件机制是基于观察者模式的实现,核心组件非常简单:

事件发布者 (Publisher) → 事件对象 (Event) → 事件监听器 (Listener)

Spring应用启动过程中会发布一系列标准事件,形成了一个完整的生命周期:

ApplicationStartingEvent    ↓ApplicationEnvironmentPreparedEvent    ↓ApplicationContextInitializedEvent    ↓ApplicationPreparedEvent    ↓ContextRefreshedEvent   ← 最常用的!    ↓ApplicationStartedEvent    ↓ApplicationReadyEvent   ← 应用完全就绪    ↓ContextClosedEvent      ← 应用关闭

我们可以监听这些事件,在不同阶段执行相应的初始化逻辑。这就像给应用装上了"触发器"!

03、实战:将烂摊子重构为优雅的监听器

让我们用ApplicationListener来重构上面的烂代码。首先,我们创建一个基础监听器:

@Component@Slf4jpublic abstract class BaseSystemListener implements ApplicationListener<ApplicationEvent> {    @Override    public void onApplicationEvent(ApplicationEvent event) {        if (shouldHandle(event)) {            log.info("[{}] 开始处理事件: {}", getListenerName(), event.getClass().getSimpleName());            long startTime = System.currentTimeMillis();            try {                doHandle(event);                long duration = System.currentTimeMillis() - startTime;                log.info("[{}] 处理完成,耗时 {}ms", getListenerName(), duration);                // 记录监控指标                Metrics.timer("listener." + getListenerName() + ".duration", duration);                Metrics.counter("listener." + getListenerName() + ".success").increment();            } catch (Exception e) {                log.error("[{}] 处理失败", getListenerName(), e);                Metrics.counter("listener." + getListenerName() + ".failure").increment();                handleFailure(e);            }        }    }    protected abstract boolean shouldHandle(ApplicationEvent event);    protected abstract void doHandle(ApplicationEvent event);    protected void handleFailure(Exception e) {        // 默认实现:只记录日志,不中断其他监听器    }    protected abstract String getListenerName();}

接下来,我们把原来的一锅炖拆分成独立的监听器:

1. 缓存初始化监听器

@Component@Slf4j@Order(1) // 缓存应该最先初始化public class CacheInitListener extends BaseSystemListener {    @Autowired    private UserCacheService userCacheService;    @Autowired    private ConfigCacheService configCacheService;    @Override    protected boolean shouldHandle(ApplicationEvent event) {        // 当应用上下文刷新完成后初始化缓存        return event instanceof ContextRefreshedEvent;    }    @Override    protected void doHandle(ApplicationEvent event) {        // 并行加载不同类型的缓存        CompletableFuture<Void> userCacheFuture = CompletableFuture.runAsync(() -> {            userCacheService.loadAllUsers();        });        CompletableFuture<Void> configCacheFuture = CompletableFuture.runAsync(() -> {            configCacheService.loadSystemConfig();        });        // 等待所有缓存加载完成        CompletableFuture.allOf(userCacheFuture, configCacheFuture).join();    }    @Override    protected void handleFailure(Exception e) {        // 缓存加载失败是严重问题,需要抛出异常        throw new RuntimeException("缓存初始化失败,系统无法启动", e);    }    @Override    protected String getListenerName() {        return "cacheInit";    }}

2. 消息队列监听器

@Component@Slf4j@Order(2) // 缓存初始化后才能监听消息public class MessageQueueListener extends BaseSystemListener {    @Autowired    private UserEventListener userEventListener;    @Autowired    private OrderEventListener orderEventListener;    @Override    protected boolean shouldHandle(ApplicationEvent event) {        // 在应用完全就绪后启动消息监听        return event instanceof ApplicationReadyEvent;    }    @Override    protected void doHandle(ApplicationEvent event) {        // 启动用户事件监听(不阻塞主线程)        new Thread(() -> {            userEventListener.startListening();        }, "user-event-listener").start();        // 启动订单事件监听        new Thread(() -> {            orderEventListener.startListening();        }, "order-event-listener").start();    }    @Override    protected String getListenerName() {        return "mqListener";    }}

3. 外部服务连接监听器

@Component@Slf4j@Order(3)@ConditionalOnProperty(name = "external.service.enabled", havingValue = "true")public class ExternalServiceListener extends BaseSystemListener {    @Autowired    private ExternalServiceHealthCheck healthCheck;    @Override    protected boolean shouldHandle(ApplicationEvent event) {        // 在应用启动时检查外部服务状态        return event instanceof ApplicationStartedEvent;    }    @Override    protected void doHandle(ApplicationEvent event) {        // 检查外部服务健康状态        boolean isHealthy = healthCheck.checkAllServices();        if (!isHealthy) {            log.warn("外部服务状态不健康,但系统继续启动");            // 可以触发降级策略            FallbackStrategy.enableDegradedMode();        }    }    @Override    protected String getListenerName() {        return "externalService";    }}

4. 定时任务监听器

@Component@Slf4jpublic class ScheduledTaskListener implements        ApplicationListener<ApplicationReadyEvent>,        SmartLifecycle {    @Autowired    private ExternalDataSyncTask syncTask;    private ScheduledExecutorService scheduler;    private volatile boolean running = false;    @Override    public void onApplicationEvent(ApplicationReadyEvent event) {        // 应用就绪后启动定时任务        start();    }    @Override    public void start() {        if (!running) {            log.info("启动定时任务管理器");            scheduler = Executors.newScheduledThreadPool(2);            // 每5分钟同步外部数据            scheduler.scheduleAtFixedRate(syncTask::syncUsers, 0, 5, TimeUnit.MINUTES);            // 每小时清理临时数据            scheduler.scheduleAtFixedRate(syncTask::cleanTempData, 1, 1, TimeUnit.HOURS);            running = true;        }    }    @Override    public void stop() {        if (running && scheduler != null) {            log.info("关闭定时任务管理器");            scheduler.shutdown();            try {                if (!scheduler.awaitTermination(10, TimeUnit.SECONDS)) {                    scheduler.shutdownNow();                }            } catch (InterruptedException e) {                scheduler.shutdownNow();                Thread.currentThread().interrupt();            }            running = false;        }    }    @Override    public boolean isRunning() {        return running;    }}

04、高级技巧:自定义事件解耦业务模块

除了监听Spring内置事件,我们还可以发布自定义事件,实现业务模块间的解耦。这是真正的"神器"用法!

场景:用户注册后的多系统联动

传统写法(紧耦合):

@Servicepublic class UserServiceImpl implements UserService {    @Autowired    private EmailService emailService;    @Autowired    private PointsService pointsService;    @Autowired    private RecommendationService recommendationService;    @Override    public User register(UserRegisterRequest request) {        // 1. 创建用户        User user = createUser(request);        // 2. 发送欢迎邮件        emailService.sendWelcomeEmail(user);        // 3. 赠送积分        pointsService.grantRegistrationPoints(user);        // 4. 生成推荐内容        recommendationService.generateForNewUser(user);        // 5. 发送系统通知        notificationService.notifyAdmins(user);        // 每新增一个需求,这里就要加一行代码...        return user;    }}

使用事件监听模式(松耦合):

// 1. 定义用户注册成功事件public class UserRegisteredEvent extends ApplicationEvent {    private final User user;    public UserRegisteredEvent(Object source, User user) {        super(source);        this.user = user;    }    public User getUser() {        return user;    }}// 2. 用户服务只负责发布事件@Servicepublic class UserServiceImpl implements UserService {    @Autowired    private ApplicationEventPublisher eventPublisher;    @Override    @Transactional    public User register(UserRegisterRequest request) {        User user = createUser(request);        // 发布用户注册事件        eventPublisher.publishEvent(new UserRegisteredEvent(this, user));        return user;    }}// 3. 邮件服务监听事件@Component@Slf4jpublic class EmailListener {    @Async  // 异步执行,不阻塞主流程    @EventListener    @Order(1)  // 最先执行    public void handleUserRegistered(UserRegisteredEvent event) {        User user = event.getUser();        log.info("发送欢迎邮件给用户: {}", user.getEmail());        // 发送邮件的具体逻辑    }}// 4. 积分服务监听事件@Component@Slf4jpublic class PointsListener {    @Async    @EventListener    @Order(2)    public void handleUserRegistered(UserRegisteredEvent event) {        User user = event.getUser();        log.info("为新用户赠送积分: {}", user.getId());        // 赠送积分的具体逻辑    }}// 5. 新增一个需求:用户注册时记录审计日志@Component@Slf4jpublic class AuditListener {    @EventListener    public void handleUserRegistered(UserRegisteredEvent event) {        // 新增需求时,只需要新增一个Listener,无需修改原有代码        log.info("记录用户注册审计日志: {}", event.getUser().getId());    }}

事件传播的事务边界处理

这里有一个重要细节:默认情况下,事件监听器会在发布事件的方法事务提交后执行。但我们可以通过@TransactionalEventListener来精确控制:

@Componentpublic class OrderListener {    // 默认:事务提交后执行    @TransactionalEventListener    public void handleOrderCreated(OrderCreatedEvent event) {        // 发送订单确认邮件    }    // 事务提交前执行    @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)    public void handleBeforeCommit(OrderCreatedEvent event) {        // 检查库存等关键业务    }    // 事务回滚后执行    @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)    public void handleAfterRollback(OrderCreatedEvent event) {        // 记录失败日志,发送警报    }    // 事务完成后执行(无论提交还是回滚)    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)    public void handleAfterCompletion(OrderCreatedEvent event) {        // 清理临时数据    }}

05、性能优化:异步事件与线程池配置

如果监听器逻辑比较耗时,我们可以使用异步执行来避免阻塞主流程:

@Configuration@EnableAsyncpublic class AsyncEventConfig implements AsyncConfigurer {    @Override    public Executor getAsyncExecutor() {        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();        executor.setCorePoolSize(5);        executor.setMaxPoolSize(10);        executor.setQueueCapacity(100);        executor.setThreadNamePrefix("event-listener-");        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());        executor.initialize();        return executor;    }    @Override    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {        return (ex, method, params) -> {            log.error("异步事件监听执行失败, method: {}", method.getName(), ex);            // 可以在这里发送警报        };    }}

然后给监听器加上@Async注解:

@Component@Slf4jpublic class DataSyncListener {    @Async    @EventListener    public void handleDataChanged(DataChangedEvent event) {        // 这里会在线程池中异步执行        syncToExternalSystem(event.getData());    }}

06、实际案例:电商系统的库存同步

让我分享一个真实的电商系统案例。我们需要在商品库存变化时,同步更新Redis缓存、更新ES搜索引擎、通知风控系统、发送库存警报。

传统做法是在库存服务中调用所有相关服务,结果代码变成了这样:

@Servicepublic class InventoryServiceImpl {    public void updateInventory(Long skuId, Integer delta) {        // 更新数据库        inventoryDao.update(skuId, delta);        // 更新Redis缓存        redisTemplate.opsForValue().set("inventory:" + skuId, getCurrentStock(skuId));        // 更新ES        esClient.updateInventory(skuId, getCurrentStock(skuId));        // 通知风控系统        riskControlService.notifyInventoryChange(skuId, delta);        // 发送低库存警报        if (getCurrentStock(skuId) < 10) {            alertService.sendLowStockAlert(skuId);        }        // 记录操作日志        auditService.logInventoryChange(skuId, delta);    }}

使用事件监听模式重构后:

@Servicepublic class InventoryServiceImpl {    @Autowired    private ApplicationEventPublisher eventPublisher;    @Transactional    public void updateInventory(Long skuId, Integer delta) {        // 只负责核心业务逻辑        Integer oldStock = inventoryDao.getStock(skuId);        inventoryDao.update(skuId, delta);        Integer newStock = oldStock + delta;        // 发布库存变化事件        eventPublisher.publishEvent(new InventoryChangedEvent(this, skuId, oldStock, newStock, delta));    }}// 各种监听器各司其职@Component class CacheUpdateListener { /* 更新Redis */ }@Component class EsSyncListener { /* 更新ES */ }@Component class RiskControlListener { /* 通知风控 */ }@Component class AlertListener { /* 发送警报 */ }@Component class AuditListener { /* 记录日志 */ }

改造后,库存服务的核心方法从30行减少到10行,而且新增同步需求时完全不需要修改库存服务代码!

07、最佳实践与避坑指南

经过多个项目的实践,我总结了一些最佳实践:

✅ 应该这样做:

  1. 1. 按事件类型分离监听器:一个监听器只处理一种事件,保持单一职责
  2. 2. 明确执行顺序:使用@Order注解或实现Ordered接口
  3. 3. 异步处理耗时操作:使用@Async避免阻塞主流程
  4. 4. 做好异常隔离:单个监听器失败不应该影响其他监听器
  5. 5. 添加监控指标:记录监听器的执行时间、成功率等

❌ 避免这些坑:

  1. 1. 不要在监听器中修改事件源:事件对象应该是不可变的
  2. 2. 小心循环依赖:A监听B事件,B监听A事件,会导致死循环
  3. 3. 避免在监听器中抛异常中断流程:除非是致命错误
  4. 4. 注意事务边界:理解@EventListener@TransactionalEventListener的区别
  5. 5. 控制监听器数量:过多的监听器会影响启动速度

性能调优配置:

# application.ymlspring:  application:    name: user-center  # 事件监听相关配置  task:    execution:      pool:        core-size: 5        max-size: 20        queue-capacity: 100    # 关闭不需要的默认事件    event:      multicast:        error-handler: customErrorHandler

结语:从"硬编码"到"事件驱动"的思维转变

三年前,我也是那个把所有初始化逻辑都塞在@PostConstruct方法里的程序员。直到一次线上事故——因为缓存初始化失败,导致整个用户注册流程瘫痪——我才意识到解耦的重要性。

ApplicationListener不仅仅是一个技术工具,它更代表了一种设计思想:响应式编程事件驱动架构。当我们把系统从"命令式"改造为"响应式",代码的可维护性、可扩展性、可测试性都会得到质的提升。

下次当你发现自己在服务类里写@Autowired注入一大堆依赖,然后在方法里依次调用时,不妨停下来想一想:这里是不是可以用事件监听来解耦?

记住:优秀的架构不是一开始就设计出来的,而是在不断重构中演进出来的。而事件监听机制,就是你重构工具箱中的一把瑞士军刀。


最后留个思考题:如果你的系统有几十个监听器,启动时需要确保某些监听器必须执行成功(如数据库连接),而某些可以失败(如非关键的外部服务),你会如何设计这样的优先级和容错机制?欢迎在评论区分享你的架构思路。

最新文章

随机文章

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