簡體   English   中英

Spring Boot 中的原型 bean 未觸發調度方法

[英]Prototyped bean not triggering Scheduled method in Spring Boot

我正在使用 Java 17、spring-boot 2.7.3 和 spring 5.3.22 依賴項。

我有如下原型bean:

@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class InsertTransactionDetailsByScheduleAPIInteractor
        implements InsertTransactionDetailsByScheduleAPIInputBoundary {

    private final InsertTransactionsInputBoundary insertTransactionsInputBoundary;
    private final RetrieveFileFromSecureFileTransferProtocolInputBoundary retrieveFileFromSecureFileTransferProtocolInputBoundary;

    public InsertTransactionDetailsByScheduleAPIInteractor(
            final InsertTransactionsInputBoundary insertTransactionsInputBoundaryParam,
            @Qualifier(Constants.PROTOTYPE_RETRIEVE_FILE_BEAN_QUALIFIER) final RetrieveFileFromSecureFileTransferProtocolInputBoundary retrieveFileFromSecureFileTransferProtocolInputBoundaryParam) {
        super();
        this.insertTransactionsInputBoundary = insertTransactionsInputBoundaryParam;
        this.retrieveFileFromSecureFileTransferProtocolInputBoundary = retrieveFileFromSecureFileTransferProtocolInputBoundaryParam;
    }

    /**
     * {@inheritDoc}
     */
    @Override
//  @Scheduled(cron = "* 30 1 * * *", zone = "America/Sao_Paulo")
    @Scheduled(initialDelay = 5, fixedRate = 1, timeUnit = TimeUnit.SECONDS)
    public void insertTransactionsBySchedule() throws Exception {
        this.insertTransactionsInputBoundary.insertTransactions(LocalDate.now(Constants.DEFAULT_ZONE_ID),
                this.retrieveFileFromSecureFileTransferProtocolInputBoundary);
    }
}
@Configuration
@RefreshScope
class FTPConfiguration {

    private final ConsulProperties consulProperties;

    public FTPConfiguration(final ConsulProperties consulPropertiesParam) {
        super();
        this.consulProperties = consulPropertiesParam;
    }

    @Bean
    @RequestScope
    @Primary
    RetrieveFileFromSecureFileTransferProtocolInputBoundary createRequestScopedRetrieveFileFromSecureFileTransferProtocolBean()
            throws Exception {
        return this.createRetrieveFileFromSecureFileTransferProtocolBean(true);
    }

    @Bean
    @RequestScope
    @Primary
    ChannelSftp createRequestScopedSecureFileTransferProtocolChannel() throws JSchException {
        return this.createSFTPChannel(true);
    }

    @Bean(destroyMethod = Constants.FTP_SESSION_BEAN_DESTROY_METHOD)
    @RequestScope
    @Primary
    Session createRequestScopeSecureFileTransferProtocolSession() throws JSchException {
        return this.createSFTPSession();
    }

    @Bean(Constants.PROTOTYPE_RETRIEVE_FILE_BEAN_QUALIFIER)
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    RetrieveFileFromSecureFileTransferProtocolInputBoundary createPrototypeScopedRetrieveFileFromSecureFileTransferProtocolBean()
            throws Exception {
        return this.createRetrieveFileFromSecureFileTransferProtocolBean(false);
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    ChannelSftp createPrototypeScopedSecureFileTransferProtocolChannel() throws JSchException {
        return this.createSFTPChannel(false);
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    Session createPrototypeScopedSecureFileTransferProtocolSession() throws JSchException {
        return this.createSFTPSession();
    }

    private RetrieveFileFromSecureFileTransferProtocolInputBoundary createRetrieveFileFromSecureFileTransferProtocolBean(
            final boolean isRequestScope) throws Exception {
        final var channelSFTP = isRequestScope ? this.createRequestScopedSecureFileTransferProtocolChannel()
                : this.createPrototypeScopedSecureFileTransferProtocolChannel();
        return new RetrieveFileFromSecureFileTransferProtocolInteractor(channelSFTP,
                new ListDirFilesFromSecureFileTransferProtocolInteractor(channelSFTP));
    }

    private ChannelSftp createSFTPChannel(final boolean isRequestScope) throws JSchException {
        final var channel = (isRequestScope ? this.createRequestScopeSecureFileTransferProtocolSession()
                : this.createPrototypeScopedSecureFileTransferProtocolSession()).openChannel("sftp");
        channel.connect(this.consulProperties.getChannelTimeout());
        return (ChannelSftp) channel;
    }

    private Session createSFTPSession() throws JSchException {
        final var session = new JSch().getSession(this.consulProperties.getUsername(), this.consulProperties.getHost(),
                this.consulProperties.getPort());
        session.setConfig("StrictHostKeyChecking", "no");
        session.setPassword(this.consulProperties.getFtpPassword());
        session.connect(this.consulProperties.getSessionTimeout());
        return session;
    }
}

我的應用程序 class:

@SpringBootApplication
@EnableCaching
@EnableScheduling
public class Application implements Closeable {

    private static ConfigurableApplicationContext run;

    public static void main(final String[] args) {
        Application.run = SpringApplication.run(Application.class, args);
    }

    @Override
    public void close() {
        Application.run.close();
    }
}

我將InsertTransactionDetailsByScheduleAPIInteractor也注釋為原型,以便在每次計划執行時都有一個內部 bean 的新實例,但不知何故,@Scheduled 方法僅在我有一個 singleton InsertTransactionDetailsByScheduleAPIInteractor bean 時運行,在我的用例中我不能擁有,否則我不會關閉 FTP 連接。 我知道在 Spring 4.3 之前,@Scheduled 方法僅適用於 Singleton bean,但如前所述,我使用的是 Spring 版本 5.3.22。

您正在使用 Spring 但這並不意味着一切都必須由 Spring 管理。 在需要時在 class 中打開 SFTP Session 並在之后關閉它沒有任何問題。 您甚至可以使用 try-with-resources,因為我希望Session是可以使用的AutoClosable

因此,簡而言之,在計划的作業中手動創建您需要的對象,並在作業完成后進行清理。 這樣,您的調度程序可以是常規的 singleton 並在其自身之后進行適當的清理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM