jjzjj

关于 spring:SFTP : BeanPostProcessor 干扰 @ServiceActivator 和 @MessagingGateway

codeneng 2023-03-28 原文

SFTP : BeanPostProcessor interfere with @ServiceActivator and @MessagingGateway

似乎 BeanPostProcessor 接口实现对@ServiceActivator 产生了影响。将 BeanPostProcessor 与 @ServiceActivator 一起使用的方式应该是什么。谢谢。

这里有完整的日志logs

以下是用于 SFTP 的 Java Config -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package com.ftp.example;

import java.io.File;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.sftp.outbound.SftpMessageHandler;
import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

import com.jcraft.jsch.ChannelSftp.LsEntry;

@Configuration
@EnableScheduling
@EnableAspectJAutoProxy
@EnableAsync
@IntegrationComponentScan
@EnableIntegration
@EnableBatchProcessing
@PropertySource("file:C:\\\\DEV\\\\workspace_oxygen\\\\ftp-example\\\\ftp-example.properties")
public class DependencySpringConfiguration {

    private Logger LOG = LoggerFactory.getLogger(DependencySpringConfiguration.class);

    @Value("${project.name}")
    private String applicationName;


    @Value("${${project.name}.ftp.server}")
    private String server;

    @Value("${${project.name}.ftp.port}")
    int port;

    @Value("${${project.name}.ftp.username}")
    private String username;

    @Value("${${project.name}.ftp.password}")
    private String password;

    @Value("${${project.name}.ftp.remote.directory}")
    private String remoteDirectory;

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public ProcessStarter processStarter() {
        return new ProcessStarter();
    }

/*  @Bean
    public LogInjector logInjector() {
        return new LogInjector();
    }*/


    @Bean
    public FTPOutService fTPOutService() {
        return new FTPOutService();
    }


    @Bean
    public SessionFactory<LsEntry> sftpSessionFactory() {
        DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory();
        sf.setHost(server);
        sf.setPort(port);
        sf.setUser(username);
        sf.setPassword(password);
        sf.setAllowUnknownKeys(true);
        return new CachingSessionFactory<LsEntry>(sf);
    }

    @Bean
    @ServiceActivator(inputChannel ="toSftpChannel")
    public MessageHandler handler() {
        SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
        handler.setRemoteDirectoryExpression(new LiteralExpression(remoteDirectory));
        handler.setFileNameGenerator(new FileNameGenerator() {

            @Override
            public String generateFileName(Message< ? > message) {
                return"fileNameToBeFtp.txt";
            }

        });
        return handler;
    }

    @MessagingGateway
    public interface MyGateway {
        @Gateway(requestChannel ="toSftpChannel")
        void sendToSftp(File file);
    }


}

我们在做 SFTP 时像这样调用网关对象

主类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class FtpExample {

    public static String[] ARGS;
    private static final Logger LOG = LoggerFactory.getLogger(FtpExample.class);

    public static void main(String[] args) throws Exception {
        ARGS = args;
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(DependencySpringConfiguration.class);

        ProcessStarter processStarter = ctx.getBean(ProcessStarter.class);
        processStarter.startService();
    }
}

其他类 -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class ProcessStarter {
    @Inject
    private FTPOutService ftpOutService;

    public void startService() {
        ftpOutService.ftpToBbg();
    }
}



public class FTPOutService {
    private static Logger log = LoggerFactory.getLogger(FTPOutService.class);

    @Inject
    private ApplicationContext appContext;

    public void ftpToBbg() {

        log.info("Starting FTP out process...");
        File file = null;
        try {
            file = new File("C:\\\\Temp\\\\log\\\\debug\\\\ftp\\\\priceindex\\\\for-upload\\\\ftp-example.txt.REQ");
            MyGateway gateway = appContext.getBean(MyGateway.class);
            gateway.sendToSftp(file);
            log.info("File {} written successfully on remote server", file);
        } catch (Exception e) {
            log.error("Error while uploading file {}", file, e);
        }
    }

}

除非我没有在上面定义的 Java Config -

中添加以下 bean 声明,否则上面的代码工作正常

1
2
3
public LogInjector logInjector() {
            return new LogInjector();
}

上面的 bean 定义有以下实现 -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class LogInjector implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
            @Override
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                // make the field accessible if defined private
                ReflectionUtils.makeAccessible(field);
                if (field.getAnnotation(Log.class) != null) {
                    if (org.slf4j.Logger.class == field.getType()) {
                        org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(bean.getClass());
                        field.set(bean, log);
                    }  else if (java.util.logging.Logger.class == field.getType()) {
                        java.util.logging.Logger log = java.util.logging.Logger.getLogger(bean.getClass().toString());
                        field.set(bean, log);
                    }
                }
            }
        });
        return bean;
    }
}


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface Log {
}

一旦在 Java Config 中添加任何 BeanPostProcessor 实现,它就会产生问题并且应用程序无法看到 toSftpChannel -

org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'toSftpChannel' available at
org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:685)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1199)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at
org.springframework.integration.support.channel.BeanFactoryChannelResolver.resolveDestination(BeanFactoryChannelResolver.java:88)
at
org.springframework.integration.support.channel.BeanFactoryChannelResolver.resolveDestination(BeanFactoryChannelResolver.java:45)
at
org.springframework.integration.gateway.MessagingGatewaySupport.getRequestChannel(MessagingGatewaySupport.java:327)
at
org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.java:368)
at
org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:477)
at
org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:429)
at
org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:420)
at
org.springframework.integration.gateway.GatewayCompletableFutureProxyFactoryBean.invoke(GatewayCompletableFutureProxyFactoryBean.java:65)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy57.sendToSftp(Unknown Source)

  • 您需要显示完整的堆栈跟踪 - MessagingGatewaySupport.send 似乎您在初始化应用程序上下文之前正在发送消息。
  • 日志在调试模式下有很多行。上传到谷歌驱动器 -drive.google.com/open?id=0ByEWhJ9QdUASNGJmNTVaZjlGd1k
  • >15:01:48.848 [main] INFO com.ftp.example.FTPOutService - Starting FTP out process... 你开始这个过程太早了 - 应用程序上下文还没有建立。您需要展示该课程。在完全构建应用程序上下文之前,您不得启动任何消息传递。
  • 我在代码中添加了 FTPOutService 类。谢谢
  • 你从哪里调用 ftpToBbg()
  • 添加了具有 main 方法的 FtpExample。谢谢
  • 您使用什么版本的 Spring Integration?如果显式声明 toSftpChannel MessageChannel bean,它是如何工作的?
  • 请看我的回答。


看看你有什么:

1
2
3
4
@Bean
public LogInjector logInjector() {
    return new LogInjector();
}

如果您将 BeanPostProcessors 声明为 @Bean,则必须使用 static 修饰符指定它们:https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-参考/core.html#beans-factorybeans-annotations

You may declare @Bean methods as static, allowing for them to be called without creating their containing configuration class as an instance. This makes particular sense when defining post-processor beans, e.g. of type BeanFactoryPostProcessor or BeanPostProcessor, since such beans will get initialized early in the container lifecycle and should avoid triggering other parts of the configuration at that point.

有关关于 spring:SFTP : BeanPostProcessor 干扰 @ServiceActivator 和 @MessagingGateway的更多相关文章

  1. ruby-on-rails - 带 Spring 锁的 Rails 4 控制台 - 2

    我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.

  2. spring.profiles.active和spring.profiles.include的使用及区别说明 - 2

    转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev

  3. ruby-on-rails - 关于 Ruby 的一般问题 - 2

    我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia

  4. ruby-on-rails - Spring 不起作用。 [未初始化常量 Spring::SID::DL] - 2

    我无法运行Spring。这是错误日志。myid-no-MacBook-Pro:myid$spring/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/lib/spring/sid.rb:17:in`fiddle_func':uninitializedconstantSpring::SID::DL(NameError)from/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/li

  5. ruby - 我怎样才能更好地了解/了解更多关于 Ruby 的知识? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?

  6. ruby - 关于 Ruby 中 Dir[] 和 File.join() 的混淆 - 2

    我在Ruby中遇到了一个关于Dir[]和File.join()的简单程序,blobs_dir='/path/to/dir'Dir[File.join(blobs_dir,"**","*")].eachdo|file|FileUtils.rm_rf(file)ifFile.symlink?(file)我有两个困惑:首先,File.join(@blobs_dir,"**","*")中的第二个和第三个参数是什么意思?其次,Dir[]在Ruby中有什么用?我只知道它等价于Dir.glob(),但是,我对Dir.glob()确实不是很清楚。 最佳答案

  7. elasticsearch源码关于TransportSearchAction【阶段三】 - 2

    1.回顾.TransportServicepublicclassTransportServiceextendsAbstractLifecycleComponentTransportService:方法:1publicfinalTextendsTransportResponse>voidsendRequest(finalTransport.Connectionconnection,finalStringaction,finalTransportRequestrequest,finalTransportRequestOptionsoptions,TransportResponseHandlerT>

  8. 关于Qt程序打包后运行库依赖的常见问题分析及解决方法 - 2

    目录一.大致如下常见问题:(1)找不到程序所依赖的Qt库version`Qt_5'notfound(requiredby(2)CouldnotLoadtheQtplatformplugin"xcb"in""eventhoughitwasfound(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentationfault,或者Illegalinstruction(coredumped)非法指令(4)ldd应用程序或者库,查看运行所依赖的库时,直接报段错误二.问题逐个分析,得出解决方法:(1)找不到程序所依赖的Qt库version`Qt_5'

  9. 【云原生】SpringCloud-Spring Boot Starter使用测试 - 2

    目录SpringBootStarter是什么?以前传统的做法使用SpringBootStarter之后starter的理念:starter的实现: 创建SpringBootStarter步骤在idea新建一个starter项目、直接执行下一步即可生成项目。 在xml中加入如下配置文件:创建proterties类来保存配置信息创建业务类:创建AutoConfiguration测试如下:SpringBootStarter是什么? SpringBootStarter是在SpringBoot组件中被提出来的一种概念、简化了很多烦琐的配置、通过引入各种SpringBootStarter包可以快速搭建出一

  10. ruby - 关于 Ruby/ChefSpec 编码风格的反馈 - 2

    我是Ruby的新手,但过去两周我一直在对Chef测试进行大量研究。该测试使用ChefSpec和Fauxhai,但它看起来不是很“像ruby”,我希望社区能给我一些编码风格的建议。有没有更好的方法来编写这样的嵌套循环?Recipe/foo/recipes/default.rbpackage"foo"doaction:installendRecipe/foo/spec/default_spec.rbrequire'chefspec'describe'foo::default'doplatforms={"debian"=>['6.0.5'],"ubuntu"=>['12.04','10.04

随机推荐