我应该在Spring中手动重置Autowired Bean的状态数据(因为它是单例)吗?

huangapple go评论101阅读模式
英文:

Should I manually reset state-data of Autowired Bean in Spring (since it is Singleton)?

问题

我在项目中使用了**org.springframework.jms.core.JmsTemplate;**来向SQS队列发送消息。

我在一个@Service中自动装配了JmsTemplate

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.jms.core.JmsTemplate;
  4. import org.springframework.stereotype.Service;
  5. @Service
  6. public class AmazonSQSPublisherImpl implements AmazonSQSPublisher {
  7. @Autowired
  8. private JmsTemplate jmsTemplate;
  9. @Override
  10. public boolean sendMessageToFifo(String queueName, String message,
  11. String messageGroupId, String messageDedupeId, long delayTime) throws EventBrokerException {
  12. jmsTemplate.setDeliveryDelay(delayTime);
  13. jmsTemplate.send(queueName, session -> {/* 这里是一些消息内容*/});
  14. }
  15. @Override
  16. public boolean sendMessage(String queueName, String message) throws EventBrokerException {
  17. jmsTemplate.convertAndSend(queueName, message);
  18. }
  19. }

这里我在jmsTemplate内部使用了setDeliveryDelay方法。所以我的问题是:
据我所知,默认情况下bean是单例的。如果我使用了jmsTemplate bean的setter,我是否应该重新设置它?在我的示例中,我是否应该在sendMessageToFifo方法的末尾添加这行代码:

  1. jmsTemplate.setDeliveryDelay(0);

如果我不添加这行代码,当我调用sendMessage而不是sendMessageToFifo时,投递延迟是否不会为零,对吗?

另外,我想问一下关于调用自动装配的bean的setter是否有什么最佳实践?

英文:

I am using org.springframework.jms.core.JmsTemplate; in my project to send messages to SQS queues.

I autowired JmsTemplate in a @Service

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.jms.core.JmsTemplate;
  4. import org.springframework.stereotype.Service;
  5. @Service
  6. public class AmazonSQSPublisherImpl implements AmazonSQSPublisher {
  7. @Autowired
  8. private JmsTemplate jmsTemplate;
  9. @Override
  10. public boolean sendMessageToFifo(String queueName, String message,
  11. String messageGroupId, String messageDedupeId, long delayTime) throws EventBrokerException {
  12. jmsTemplate.setDeliveryDelay(delayTime);
  13. jmsTemplate.send(queueName, session -> {/* somemessage here*/});
  14. }
  15. @Override
  16. public boolean sendMessage(String queueName, String message) throws EventBrokerException {
  17. jmsTemplate.convertAndSend(queueName, message);
  18. }
  19. }

Here I use setDeliveryDelay inside the jmsTemplate. So my question is:
As I known, bean is singleton by default. if I used the setter of the jmsTemplate bean, should I reset it? In my example, should I add this at the end of method sendMessageToFifo:

  1. jmsTemplate.setDeliveryDelay(0);

If I don't add this, when I call sendMessage rather than sendMessageToFifo, the delivery delay will not be zero, right?

Also, I want to ask if any best practices for call setter of autowired bean??

答案1

得分: 4

所有的bean默认都是单例的,所以是的,一种方法是将其重置。

但在我看来,那是一个不好的解决方案。

你应该做的是定义一个专门的 JmsTemplate @Bean,在其中进行自定义配置,然后在需要的地方进行 autowire

如果你在其他任何地方需要另一个 JmsTemplate,你可以定义第二个 @Bean,并通过使用 @Qualifiers 来区分这两者。

英文:

All beans are singleton by default, so yes one way is to reset it.

But imho thats an ugly solution.

What you should do is to define a dedicated JmsTemplate @Bean that you custom configure and then autowire where you need.

If you need another JmsTemplate for any other place you define a second @Bean and you separate these two by using @Qualifiers.

答案2

得分: 2

所有的 bean 默认都是单例的,所以我认为你应该按照你的建议进行重置。

正如在 Spring 的文档 中所述:

> 单例作用域是 Spring 中的默认作用域。(...)
> 当一个 bean 是单例时,容器将只管理一个共享的 bean 实例,对于与该 bean 定义的 id 匹配的所有 bean 请求将导致 Spring 容器返回那个特定的 bean 实例。

这意味着下一次调用 jmsTemplate 时,它将具有先前添加的状态数据。

还有其他的 bean 作用域,你可以在上面的源代码中查看。

关于使用 @AutoWired 注解进行字段注入,通常不被认为是一种好的做法,因为存在各种问题,详见这里(最好使用构造函数或 setter 注入)。

英文:

All beans are singleton by default, so I think that you should reset it as you suggest.

As stated in Spring`s documentation:

> The singleton scope is the default scope in Spring. (...)
> When a bean is a singleton, only one shared instance of the bean will
> be managed, and all requests for beans with an id or ids matching that
> bean definition will result in that one specific bean instance being
> returned by the Spring container.

This means that the next time jmsTemplate is called, it will have its previously added state-data.

There are other bean scopes, which you can view in the source above.

In terms of using field injection via the @AutoWired annotation, it is generally not considered a good practice due to various issues listed here (prefer constructor or setter injection instead).

huangapple
  • 本文由 发表于 2020年3月16日 04:39:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/60697448.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定