Spring singleton和prototype bean之间的区别是什么?
我是春天的新手,我读到: 基本上,bean具有定义其在应用程序上存在的范围 Singleton:表示每个SpringIOC容器对单个对象实例的单个bean定义 Prototype:表示对任意数量的对象实例的单个bean定义Spring singleton和prototype bean之间的区别是什么?,spring,dependency-injection,Spring,Dependency Injection,我是春天的新手,我读到: 基本上,bean具有定义其在应用程序上存在的范围 Singleton:表示每个SpringIOC容器对单个对象实例的单个bean定义 Prototype:表示对任意数量的对象实例的单个bean定义 那么“对象实例”是什么呢?原型范围=每次注入/查找新对象时都会创建一个新对象。每次都将使用newsomeclass() 单例作用域=(默认)每次注入/查找同一对象时都返回该对象。在这里,它将实例化SomeClass的一个实例,然后每次返回它 另请参见: 它们都是创造性的设
那么“对象实例”是什么呢?原型范围=每次注入/查找新对象时都会创建一个新对象。每次都将使用
newsomeclass()
单例作用域=(默认)每次注入/查找同一对象时都返回该对象。在这里,它将实例化SomeClass
的一个实例,然后每次返回它
另请参见:
Prototype每次都会返回一个新实例。添加到上面。.不要与java单例混淆。 根据JAVA规范,singleton意味着每个JVM只创建该bean的一个实例。 但在spring中,singleton意味着每个应用程序上下文将为该特定bean创建一个实例。
所以,如果您的应用程序有多个上下文,您仍然可以为该bean提供多个实例。Singleton是应用程序中的同一个实例
Prototype是getBean的每个新请求的新实例Singleton作用域:对于Singleton作用域,使用提供的bean定义创建一个且只有一个bean实例,对于相同bean的后续请求,Spring容器将返回相同的实例 从Spring文档中: 。。当您定义一个bean定义并将其范围限定为单例时, SpringIOC容器只创建一个对象实例 由该bean定义定义。此单个实例存储在 此类单例bean的缓存,以及所有后续请求和 该命名bean的引用将返回缓存的对象 例如: 比方说,我们定义了一个bean
accountDao
,如下所示:
<bean id="accountDao" class="" />
<bean id="accountDao" class="" scope="prototype"/>
Spring最初将创建accountDao
bean并缓存它。然后对于someBean
以及anotherBean
,它将提供与accountDao
相同的实例
注意:如果bean定义没有指定作用域,那么Singleton是默认作用域
原型范围:对于原型范围,对于bean的每个请求,将创建并返回一个新的bean实例。这类似于在java中为类调用new操作符
例如:
比方说,我们定义了一个beanaccountDao
,如下所示:
<bean id="accountDao" class="" />
<bean id="accountDao" class="" scope="prototype"/>
对于someBean和另一个Bean,Spring将返回accountDao对象的两个独立实例
一个重要的区别是,对于prototype范围,Spring不管理bean的整个生命周期,清理需要由客户机代码完成
从Spring文档中:
Spring不管理原型bean的整个生命周期:
容器实例化、配置和以其他方式组装
原型对象,并将其交给客户机,无需进一步记录
那个原型的实例。因此,虽然初始化的生命周期
在
对于原型,配置的销毁生命周期回调不可用
打电话。客户机代码必须清理原型范围的对象和
释放原型bean所持有的昂贵资源
让我们通过代码简单地查找一下 下面是一个TennisCoach Bean,默认范围为
singleton
@Component
@Scope("singleton")
public class TennisCoach implements Coach {
public TennisCoach(){
}
@Autowired
public void setFortuneService(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Practice your backhand volley";
}
@Override
public String getDailyFortune() {
return "Tennis Coach says : "+fortuneService.getFortune();
}
}
下面是一个具有原型范围的TennisCoach Bean
@Component
@Scope("prototype")
public class TennisCoach implements Coach {
public TennisCoach(){
System.out.println(">> TennisCoach: inside default constructor");
}
@Autowired
public void setFortuneService(FortuneService fortuneService) {
System.out.println(">> Tennis Coach: inside setFortuneService");
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Practice your backhand volley";
}
@Override
public String getDailyFortune() {
return "Tennis Coach says : "+fortuneService.getFortune();
}
}
以下是一个主要类:
public class AnnotationDemoApp {
public static void main(String[] args) {
// read spring config file
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
// get the bean from the spring container
Coach theCoach = context.getBean("tennisCoach",Coach.class);
Coach alphaCoach = context.getBean("tennisCoach",Coach.class);
// call a method on the bean
System.out.println("Are the two beans same :" + (theCoach==alphaCoach));
System.out.println("theCoach : " + theCoach);
System.out.println("alphaCoach: "+ alphaCoach);
context.close()
}
}
对于单例范围,输出为:
Are the two beans same :true
theCoach : com.springdemo.TennisCoach@2a53142
alphaCoach: com.springdemo.TennisCoach@2a53142
Are the two beans same :false
theCoach : com.springdemo.TennisCoach@1b37288
alphaCoach: com.springdemo.TennisCoach@1a57272
对于原型范围,输出为:
Are the two beans same :true
theCoach : com.springdemo.TennisCoach@2a53142
alphaCoach: com.springdemo.TennisCoach@2a53142
Are the two beans same :false
theCoach : com.springdemo.TennisCoach@1b37288
alphaCoach: com.springdemo.TennisCoach@1a57272
我想补充一些额外的信息,帮助我们找出上述句子中“对象实例”的含义。Spring文档中的这一段试图定义“对象实例”: 当您创建一个bean定义时,您创建了一个菜谱,用于创建由该bean定义定义的类的实际实例。豆子定义是菜谱的想法很重要,因为它意味着, 与类一样,您可以从单个配方创建多个对象实例
因此,正如上面部分提到的,每个bean定义都可以被视为一个类(从面向对象的角度)。根据您在其中定义的数据(例如范围,…),该类(或bean定义)可能只有一个对象实例(只有一个共享实例的单例范围)或任意数量的对象实例(例如,每次请求特定bean时通过创建新的bean实例来定义原型范围).原型范围:每次注入新对象时都会创建一个新对象。
单例作用域:每次注入时都返回相同的对象 Prototype作用域用于所有有状态的bean,而singleton作用域应用于无状态bean。 让我用我的例子来解释。请自行复制并运行,以获得清晰的理解。 考虑一个界面教练。
public interface Coach {
public String getDailyWorkout();
public String getDailyFortune();
}
我们有另一个名为TrackCoach的类,它实现了Coach
public class TrackCoach implements Coach {
private FortuneService fortuneService;
public TrackCoach(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Run a hard 5k";
}
@Override
public String getDailyFortune() {
return "Just Do it: " + fortuneService.getFortune();
}
}
现在有了一个服务接口
public interface FortuneService {
public String getFortune();
}
它是由我们班的幸福服务来实现的
public class HappyFortuneService implements FortuneService {
@Override
public String getFortune() {
return "Today is your lucky day!";
}
}
让我们连接这两个类,并使用Xml将一个类的对象bean注入另一个类。让我们执行依赖项注入。注意,我们也可以使用java注释来实现这一点
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Define your beans here -->
<!-- define the dependency -->
<bean id = "myFortuneService"
class = "com.luv2code.springdemo.HappyFortuneService">
</bean>
<bean id = "myCoach"
class = "com.luv2code.springdemo.TrackCoach"
scope = "singleton">
<!-- set up construction injection -->
<constructor-arg ref = "myFortuneService" />
</bean>
</beans>
运行上述代码后,您将看到以下结果
Pointing to the same object: false
Memory location for theCoach: com.luv2code.springdemo.TrackCoach@6d4d203d
Memory location for alphaCoach: com.luv2code.springdemo.TrackCoach@627fbcda
public class PrototypeClass {
PrototypeClass()
{
System.out.println("prototype class is created"+this.toString());
}
}
for(int i=0;i<10;i++) {
PrototypeClass pct= (PrototypeClass) context.getBean("protoClass");
}
<bean id="protoClass" class="Spring.PrototypeClass" scope="prototype</bean>