[英]How Singleton bean can be Autowired in different places spring boot
I'm confused at this point, and i know all spring boot applications beans are singleton, according to my understanding if we have class annotated with @Service
annotation that bean can be @Autowired
in only one class (correct me if i'm wrong) here is the code that works fine, but i'm trying to understand how it works? 在这一点上,我很困惑,根据我的理解,如果我们使用@Service
批注对类进行注释,那么bean只能在一个类中进行@Autowired
(如果我错了,请纠正我) )这是可以正常工作的代码,但我试图了解它的工作原理? how one bean can be @Autowired
in two different classes? 如何在两个不同的类中@Autowired
一个bean?
How SampleService
bean can be @Autowired
in SampleController2
and SampleController3
at a time ? 如何在SampleController2
和SampleController3
中一次@Autowired
SampleService
bean?
And is this recommended approach? 这是推荐的方法吗? and in this case two threads can parallely change the data inside bean? 在这种情况下,两个线程可以并行更改bean中的数据?
SampleController2
@RestController
@RequestMapping(value="samplemock")
public class SampleController2 {
@Autowired
private SampleService2 sampleservice2;
@RequestMapping(value="/mock1",method=RequestMethod.GET)
public void mockCall1() {
sampleservice2.m1();
}
}
SampleController3
@RestController
@RequestMapping(value="samplemock2")
public class SampleController3 {
@Autowired
private SampleService2 sampleservice2;
@RequestMapping(value="/mock1",method=RequestMethod.GET)
public void mockCall1() {
sampleservice2.m1();
}
}
SampleService2
@Service
public class SampleService2 {
public void m1() {
System.out.println("bean is autowired");
}
}
By default, as you mentioned, all Spring beans are singletons, but your second assumption is wrong: the same bean can be autowired in many other beans. 正如您提到的,默认情况下,所有Spring Bean都是单例的,但是您的第二个假设是错误的:同一bean可以在许多其他bean中自动装配。
In fact that's the whole point of them being singletons. 实际上,这就是单身人士的全部要点。
That also means two different threads could change the state of the same bean indeed. 这也意味着两个不同的线程确实可以更改同一bean的状态。 You would most of the time want to keep your beans stateless for that reason. 出于这种原因,您大多数时候都希望使bean保持无状态。
If you really ever need to have one different instance of a bean for each place where it is autowired, you can change the scope of that bean to prototype
. 如果确实需要在每个自动装配的位置使用一个bean的不同实例,则可以将该bean的范围更改为prototype
。 See Spring bean scopes docs . 参见Spring bean scopes文档 。
Here is a simplified view of what Spring does on startup: 这是Spring在启动时所做的简化视图:
// Create bean: sampleService2
SampleService2 sampleService2 = new SampleService2();
// Create bean: sampleController2
SampleController2 sampleController2 = new SampleController2();
sampleController2.sampleservice2 = sampleService2; // because @Autowired
// Create bean: sampleController3
SampleController3 sampleController3 = new SampleController3();
sampleController3.sampleservice2 = sampleService2; // because @Autowired
As you can see, the singleton bean sampleService2
is autowired into both sampleController2
and sampleController3
. 如您所见,单例bean sampleService2
被自动连接到sampleController2
和sampleController3
。
The beans are added to a repository, so you can look them up by name or type at any later point in time. Bean被添加到存储库中,因此您可以在以后的任何时间按名称或类型进行查找。
The intention behind dependency injection and inversion of control is simple: 依赖项注入和控制反转的意图很简单:
While I feel like the last point answers your primary question fairly tacitly, I'll elaborate - in a DI context, the only thing that really matters are enforceable contracts. 尽管我觉得最后一点很默契地回答了您的主要问题,但我会详细说明-在直接投资的背景下,唯一真正重要的是可强制执行的合同。 That is to say, if your service subscribes to a specific type of contract, and you have a component which wishes to inject a service which fulfills that contract, then your DI layer should faithfully register a service which can fulfill that contract. 就是说,如果您的服务订阅了特定类型的合同,并且您有一个组件希望注入能够履行该合同的服务,那么您的DI层应该如实地注册一个可以履行该合同的服务。
You get into fun and exciting stuff with bean priority, qualifiers and application profiles at that point, but this is the general idea. 此时,您将获得有关bean优先级,限定符和应用程序配置文件的有趣知识,但这是总的想法。
For a concrete example: javax.sql.DataSource
is an interface which is implemented by many JDBC-backed solutions, such as MySQL, Postgres, Oracle, and others. 举一个具体的例子: javax.sql.DataSource
是一个由许多JDBC支持的解决方案(例如MySQL,Postgres,Oracle等)实现的接口。 If you wish to have two different beans which talk to two different databases, but you want to be able to use those interchangeably, then you define a bean of type DataSource
to use and configure which data source gets created. 如果你想有两个不同的豆子这跟两个不同的数据库,但要能够交替使用的,那么你定义类型的bean的DataSource
使用和配置的数据源被创建。 Again, this does involve things like @Qualifier
to ensure you wire in the most specific bean at the most appropriate time. 同样,这确实涉及到@Qualifier
事情,以确保您在最合适的时间连接最具体的bean。
Also, that last point is fairly important to answer this part of your question: 此外,最后一点对于回答问题的这一部分非常重要:
... and in this case two threads can parallely change the data inside bean? ...并且在这种情况下,两个线程可以并行更改Bean中的数据?
It is very unwise to create an injectable bean with its own inherent state. 创建具有其固有状态的可注入bean是非常不明智的。 That is, if you have SampleService
attach itself to some sort of cached state with a collection inside of it, you're basically violating expectations since you don't know when or how often that collection is going to have elements added to it or removed from it. 也就是说,如果您让SampleService
将其自身附加到某种内部带有集合的缓存状态,则基本上是在违反期望,因为您不知道该集合何时或多SampleService
添加或删除元素从中。
The better convention is to have beans which can reference stateful services, but don't store that state in the bean itself (such as a database connection, but not entire database tables). 更好的约定是让bean可以引用有状态服务,但不要将该状态存储在bean本身中(例如数据库连接,而不是整个数据库表)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.