热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

SFTP:BeanPostProcessorinterferewith@ServiceActivatorand@


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 sftpSessionFactory() {

        DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory();

        sf.setHost(server);

        sf.setPort(port);

        sf.setUser(username);

        sf.setPassword(password);

        sf.setAllowUnknownKeys(true);

        return new CachingSessionFactory(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?如果显式声明 toSftpChannelMessageChannel 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.







推荐阅读
author-avatar
手机用户2602910773
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有