Skip to content

一个智能内容生成服务,结合通义千问API和文件监听技术,实现自动化的内容生成与分发(说的隐晦点😜😜😜)

License

Notifications You must be signed in to change notification settings

dk900912/smart-content-generator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Java support Spring Boot support License

🚀 Smart Content Generator

智能内容生成服务 · 让AI为你创作精彩内容

一个智能内容生成服务,结合通义千问API和文件监听技术,实现自动化的内容生成与分发(不能多说了,😜😜😜)

功能特性

  • 🖼️ 自动检测指定目录中的图片文件
  • 🧠 利用阿里云通义千问大模型分析图片内容
  • 📄 自动生成高质量的中文内容
  • 📨 支持自动邮件发送生成的内容

技术栈

  • Java 21+
  • Spring Boot 3.5
  • 阿里云DashScope API
  • 文件监听器(File Watcher

一些过程性的思考

Spring内部一个组件同时实现这三个接口很常见!

1. 为什么实现ApplicationContextAware

  • ApplicationContextAware接口提供了一种机制,允许在Bean的初始化(initializeBean)阶段,获取到ApplicationContext实例,这是依赖ApplicationContextAwareProcessor实现的。 既然有了ApplicationContext,那么就可以获取到实例化FileSystemWatcher时所需要的FileWatcherProperties这一Bean

2. 为什么使用FactoryBean

  • FactoryBean主要用于实例化逻辑比较复杂的Bean,而FileSystemWatcher实例化确实又可以很复杂,必须要为该实例配置FileFilterSnapshotStateRepositoryFileChangeListener等组件才能发挥作用,这些组件往往又需要基于FileWatcherProperties中的内容来决策各自实例化策略,甚至是需要独自实现自己的FileFilterSnapshotStateRepository来替换掉默认的能力。

3. 为什么实现SmartLifecycle

public interface SmartLifecycle extends Lifecycle, Phased {
  default boolean isAutoStartup() { return true; }
  default void stop(Runnable callback) {
  	stop();
  	callback.run();
  }
  default int getPhase() { return DEFAULT_PHASE; }
}

LifecycleSmartLifecycle接口都用于管理Bean的生命周期,但SmartLifecycle提供了更精细的控制:

  • Lifecycle提供了基本的start()isRunning()stop()方法,它适合那些生命周期管理比较简单、不需要关心启动顺序或自动启动条件的组件;此外,其中 start()stop()方法需要手动调用,比如分别监听ContextStartedEventContextClosedEvent事件以手动调用其start()close()方法。

  • SmartLifecycle继承自Lifecycle,并增加了更高级的控制,包括:

    • isAutoStartup(): 决定是否应该在容器启动时自动启动(默认为true)。
    • stop(Runnable callback): 允许更优雅的停止,当组件完全停止后,会执行传入的callback
    • getPhase(): 这是最关键的区别之一,它定义了组件在启动和关闭阶段的顺序。具有较低phase值的组件会先启动,后停止,这对于有依赖关系的组件至关重要。
    • 最为重要的一点:
      • ConfigurableApplicationContext在执行refresh()过程中会自动调用DefaultLifecycleProcessoronRefresh()方法,最终自动启动所有的SmartLifecycle;同样地,ConfigurableApplicationContext在执行close()逻辑过程中也会自动调用DefaultLifecycleProcessoronClose()方法,最终自动关闭所有的SmartLifecycle
      • ConfigurableApplicationContext中的doClose()方法会由其close()方法或JVM shutdown钩子自动调用,两条路最终均会走到DefaultLifecycleProcessoronClose()方法,以自动关闭所有的SmartLifecycle

显然,SmartLifecycle更牛逼,但弃用Lifecycle最重要的因素是它无法随着ConfigurableApplicationContext的状态来实现自动启停,即ConfigurableApplicationContext的刷新与关闭会自动触发DefaultLifecycleProcessoronRefresh()onClose()方法的执行,而DefaultLifecycleProcessoronRefresh()方法中明确屏蔽了Lifecycle,即使DefaultLifecycleProcessoronClose()方法包含了Lifecycle的关闭逻辑,但由于isRunning()false,自然Lifecyclestop()方法压根也不会被调用。

附:代码片段-1

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {
  protected void finishRefresh() {
    // Reset common introspection caches in Spring's core infrastructure.
    resetCommonCaches();

    // Clear context-level resource caches (such as ASM metadata from scanning).
    clearResourceCaches();

    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));
  }

  /**
   * Actually performs context closing: publishes a ContextClosedEvent and
   * destroys the singletons in the bean factory of this application context.
   * <p>Called by both {@code close()} and a JVM shutdown hook, if any.
   *
   * @see #close()
   * @see #registerShutdownHook()
   */
  protected void doClose() {
    // Check whether an actual close attempt is necessary...
    if (this.active.get() && this.closed.compareAndSet(false, true)) {
      if (logger.isDebugEnabled()) {
        logger.debug("Closing " + this);
      }

      try {
        // Publish shutdown event.
        publishEvent(new ContextClosedEvent(this));
      } catch (Throwable ex) {
        logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
      }

      // Stop all Lifecycle beans, to avoid delays during individual destruction.
      if (this.lifecycleProcessor != null) {
        try {
          this.lifecycleProcessor.onClose();
        } catch (Throwable ex) {
          logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
        }
      }

      // Destroy all cached singletons in the context's BeanFactory.
      destroyBeans();

      // Close the state of this context itself.
      closeBeanFactory();

      // Let subclasses do some final clean-up if they wish...
      onClose();

      // Reset common introspection caches to avoid class reference leaks.
      resetCommonCaches();

      // Reset local application listeners to pre-refresh state.
      if (this.earlyApplicationListeners != null) {
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
      }

      // Reset internal delegates.
      this.applicationEventMulticaster = null;
      this.messageSource = null;
      this.lifecycleProcessor = null;

      // Switch to inactive.
      this.active.set(false);
    }
  }
}

附:代码片段-2

public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {

    @Override
    public void onRefresh() {
        if (checkpointOnRefresh) {
            checkpointOnRefresh = false;
            new CracDelegate().checkpointRestore();
        }
        if (exitOnRefresh) {
            Runtime.getRuntime().halt(0);
        }

        this.stoppedBeans = null;
        try {
            startBeans(true);
        } catch (ApplicationContextException ex) {
            stopBeans();
            throw ex;
        }
        this.running = true;
    }

    private void startBeans(boolean autoStartupOnly) {
        Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
        Map<Integer, LifecycleGroup> phases = new TreeMap<>();

        lifecycleBeans.forEach((beanName, bean) -> {
            if (!autoStartupOnly || isAutoStartupCandidate(beanName, bean)) {
                int startupPhase = getPhase(bean);
                phases.computeIfAbsent(startupPhase, phase -> new LifecycleGroup(phase, lifecycleBeans, autoStartupOnly))
                        .add(beanName, bean);
            }
        });

        if (!phases.isEmpty()) {
            phases.values().forEach(LifecycleGroup::start);
        }
    }

    // 纯碎的 Lifecycle 压根不会考虑
    private boolean isAutoStartupCandidate(String beanName, Lifecycle bean) {
        Set<String> stoppedBeans = this.stoppedBeans;
        return (stoppedBeans != null ? stoppedBeans.contains(beanName) :
                (bean instanceof SmartLifecycle smartLifecycle && smartLifecycle.isAutoStartup()));
    }
}

About

一个智能内容生成服务,结合通义千问API和文件监听技术,实现自动化的内容生成与分发(说的隐晦点😜😜😜)

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages