Spring SpringBootApplication class 内部的自动装配在几乎相同的应用程序之间表现不同
Spring Autowire inside of SpringBootApplication class is behaving differently between nearly identical applications
我有两个 SpringBoot 应用程序,我在其中使用 RabbitMQ 跨队列传递消息。一个应用程序用于发送消息,另一个用于侦听已发送的消息。每个应用程序都包含一个 @SpringBootApplication 文件,该文件在属性级别具有一个 @Autowired 依赖项(一个应用程序具有发送者,另一个应用程序具有侦听器)并且每个应用程序都有一个单独的 Spring @Configuration 文件,它每个声明一个 bean(一个有发送者,一个有接收者)。
出于某种原因,发送方应用程序的注入没有问题,但是,即使 bean 在我的应用程序上下文中,接收方应用程序也没有在 @Autowire 注入。我使用示例应用程序作为向我们公司演示 RabbitMQ/SpringAMQP 以及 Spring 引导和微服务的一种方式。下面是发送方应用程序的代码,后面是接收方应用程序。如果我将 Receiver 应用程序更改为使用 Setter 注入,它工作得很好,我很好奇为什么其中一个有效而另一个无效。 Receiver 应用程序在其 main 方法中调用 receiver.receive() 时崩溃,如下所示:
线程异常 "main" java.lang.NullPointerException
在 com.bettercloud.SpringAmqpApplication.main(SpringAmqpApplication.java:17)
接收方应用程序:
@SpringBootApplication
public class SpringAmqpApplication {
@Autowired
static Recv receiver;
public static void main(String[] args) throws IOException,InterruptedException {
SpringApplication.run(SpringAmqpApplication.class, args);
receiver.receive();
}
}
@Configuration
public class Config {
@Bean
public Recv recv(){
return new Recv();
}
}
public class Recv {
private final static String QUEUE_NAME = "task_queue";
public void receive()
throws java.io.IOException,
InterruptedException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
channel.basicQos(1);
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(QUEUE_NAME, false, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
doWork(message);
System.out.println(" [x] Done");
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
private static void doWork(String task) throws InterruptedException {
for (char ch: task.toCharArray()) {
if (ch == '.') Thread.sleep(1000);
}
}
}
发件人申请:
@SpringBootApplication
public class SpringAmqpProducerApplication {
@Autowired
static Send sender;
public static void main(String[] args) throws IOException {
SpringApplication.run(SpringAmqpProducerApplication.class, args);
sender.send(null);
}
}
@Configuration
public class Config {
@Bean
public Send send(){
return new Send();
}
}
public class Send {
private final static String QUEUE_NAME = "task_queue";
public static void send(String[] argv)
throws java.io.IOException {
Connection connection = null;
Channel channel = null;
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
connection = factory.newConnection();
channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
String message = getMessage(argv);
channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
} finally {
channel.close();
connection.close();
}
}
private static String getMessage(String[] strings){
if (strings == null || strings.length < 1)
return "Hello World!";
return joinStrings(strings, " ");
}
private static String joinStrings(String[] strings, String delimiter) {
int length = strings.length;
if (length == 0) return "";
StringBuilder words = new StringBuilder(strings[0]);
for (int i = 1; i < length; i++) {
words.append(delimiter).append(strings[i]);
}
return words.toString();
}
}
我认为注入根本不起作用,因为您尝试注入静态字段,这不适用于 Spring。从您的字段(以及您的方法,因为没有理由它们也是静态的)中删除静态标识符,您的应用程序应该可以正常工作。
发件人工作,因为发送方法是静态的,所以你不需要一个对象来调用该方法。
不确定这是否有帮助,但是发送 class 中的 send() 方法是静态的,而接收 class 中的 receive() 方法不是静态的。
我有两个 SpringBoot 应用程序,我在其中使用 RabbitMQ 跨队列传递消息。一个应用程序用于发送消息,另一个用于侦听已发送的消息。每个应用程序都包含一个 @SpringBootApplication 文件,该文件在属性级别具有一个 @Autowired 依赖项(一个应用程序具有发送者,另一个应用程序具有侦听器)并且每个应用程序都有一个单独的 Spring @Configuration 文件,它每个声明一个 bean(一个有发送者,一个有接收者)。
出于某种原因,发送方应用程序的注入没有问题,但是,即使 bean 在我的应用程序上下文中,接收方应用程序也没有在 @Autowire 注入。我使用示例应用程序作为向我们公司演示 RabbitMQ/SpringAMQP 以及 Spring 引导和微服务的一种方式。下面是发送方应用程序的代码,后面是接收方应用程序。如果我将 Receiver 应用程序更改为使用 Setter 注入,它工作得很好,我很好奇为什么其中一个有效而另一个无效。 Receiver 应用程序在其 main 方法中调用 receiver.receive() 时崩溃,如下所示:
线程异常 "main" java.lang.NullPointerException 在 com.bettercloud.SpringAmqpApplication.main(SpringAmqpApplication.java:17)
接收方应用程序:
@SpringBootApplication
public class SpringAmqpApplication {
@Autowired
static Recv receiver;
public static void main(String[] args) throws IOException,InterruptedException {
SpringApplication.run(SpringAmqpApplication.class, args);
receiver.receive();
}
}
@Configuration
public class Config {
@Bean
public Recv recv(){
return new Recv();
}
}
public class Recv {
private final static String QUEUE_NAME = "task_queue";
public void receive()
throws java.io.IOException,
InterruptedException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
channel.basicQos(1);
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(QUEUE_NAME, false, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
doWork(message);
System.out.println(" [x] Done");
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
private static void doWork(String task) throws InterruptedException {
for (char ch: task.toCharArray()) {
if (ch == '.') Thread.sleep(1000);
}
}
}
发件人申请:
@SpringBootApplication
public class SpringAmqpProducerApplication {
@Autowired
static Send sender;
public static void main(String[] args) throws IOException {
SpringApplication.run(SpringAmqpProducerApplication.class, args);
sender.send(null);
}
}
@Configuration
public class Config {
@Bean
public Send send(){
return new Send();
}
}
public class Send {
private final static String QUEUE_NAME = "task_queue";
public static void send(String[] argv)
throws java.io.IOException {
Connection connection = null;
Channel channel = null;
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
connection = factory.newConnection();
channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
String message = getMessage(argv);
channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
} finally {
channel.close();
connection.close();
}
}
private static String getMessage(String[] strings){
if (strings == null || strings.length < 1)
return "Hello World!";
return joinStrings(strings, " ");
}
private static String joinStrings(String[] strings, String delimiter) {
int length = strings.length;
if (length == 0) return "";
StringBuilder words = new StringBuilder(strings[0]);
for (int i = 1; i < length; i++) {
words.append(delimiter).append(strings[i]);
}
return words.toString();
}
}
我认为注入根本不起作用,因为您尝试注入静态字段,这不适用于 Spring。从您的字段(以及您的方法,因为没有理由它们也是静态的)中删除静态标识符,您的应用程序应该可以正常工作。
发件人工作,因为发送方法是静态的,所以你不需要一个对象来调用该方法。
不确定这是否有帮助,但是发送 class 中的 send() 方法是静态的,而接收 class 中的 receive() 方法不是静态的。