春季默认范围是单身吗?

你能否解释为什么Spring为下面显示的bean配置创建了两个对象,因为默认情况下spring默认范围是singleton?

Spring配置在这里:

         

Spring的默认范围单例。 只是你对单身人士意味着什么的想法与Spring定义单身人士的方式不符。

如果你告诉Spring使用不同的id和相同的类创建两个单独的bean,那么你将得到两个单独的bean,每个bean都有singleton范围。 所有单例作用域的意思是当你引用具有相同id的东西时,你会得到相同的bean实例。

以下是Spring文档如何定义单例范围 :

只管理单个bean的一个共享实例,并且对具有与该bean定义匹配的id或id的bean的所有请求都会导致Spring容器返回一个特定的bean实例。

单例范围意味着使用相同的id检索相同的bean,即all。 测试没有两个id引用相同的类会妨碍使用map作为bean,并且通过使用BeanFactories代理事情会变得复杂。 对于Spring来说,这将涉及很多工作而没有什么好处,相反它相信用户知道他们在做什么。

为同一个bean定义两个名称的方法是使用别名 :

在bean定义本身中,您可以为bean提供多个名称,方法是使用id属性指定的最多一个名称和name属性中的任意数量的其他名称。 这些名称可以是同一个bean的等效别名,并且在某些情况下很有用,例如允许应用程序中的每个组件通过使用特定于该组件本身的bean名称来引用公共依赖项。

但是,指定实际定义bean的所有别名并不总是足够的。 有时需要为其他地方定义的bean引入别名。 在大型系统中通常就是这种情况,其中配置在每个子系统之间分配,每个子系统具有其自己的一组对象定义。 在基于XML的配置元数据中,您可以使用该元素来完成此任务。

因此,如果在bean配置中添加名称:

   

或为其他地方定义的bean创建别名:

  

那么“customer”和“customer2”将引用相同的bean实例。

Spring默认范围是单例,它将为所有实例创建一个对象,除非您明确指定范围为原型。 您尚未发布弹簧配置。 请发布,它会给出一个更好的主意。

您正在声明同一类的两个bean。 那不一样。

 @Component("springTestClass") public class SpringTestClass{ private int randomNumber = 0; public SpringTestClass(){ randomNumber = new Random().nextInt(2000); } public int getRandomNumber(){ return this.randomNumber; } } 

并尝试在两个地方访问此bean,数量将相同。 但你所做的是创建两个独立的bean。

如果你想检查这是否有效,请尝试:

 public class Main{ public static void main(String[] args){ ApplicationContext ctx = ....; SpringTestClass testObject1 = (SpringTestClass)ctx.getBean("springTestClass"); SpringTestClass testObject2 = (SpringTestClass)ctx.getBean("springTestClass"); System.out.println(testObject1.getRandomNumber() == testObject2.getRandomNumber()); } } 

如果它是同一个实例,则此代码应返回true; 但是在SpringTestClass中,您可以添加@Scope(“prototype”)注释。 输出将为false

与其他人提到的一样,应该从您发布的代码中创建两个bean。 单例定义如下(来自Spring文档: Singleton Scope )

只管理单个bean的一个共享实例,并且对具有与该bean定义匹配的id或id的bean的所有请求都会导致Spring容器返回一个特定的bean实例。

为了增加清晰度,“共享实例”背后的含义在上面的段落中解释:

该命名bean的所有后续请求和引用都返回缓存对象

创建单例bean时,只实例化和缓存一个bean对象。 这仅指bean,而不是bean可能是其实例的任何类。 例如,

        

在这个组成的配置中,“myOtherBean1”和“myOtherBean2”引用了相同的“myBean”bean,因此引用了相同的“myPackage.myClass”实例。 如果您更改了代码以添加第二个“myPackage.myClass”bean,那么它将与“myBean”不同。

要完全理解这一点,还可以参考其他Spring范围:原型。 从Prototype Scope的Spring文档:

bean的非单例原型范围部署导致每次发出对该特定bean的请求时都会创建一个新的bean实例。

这意味着如果我们使用与上面相同的Spring XML,“myOtherBean1”和“myOtherBean2”将各自接收自己的“myBean”的不同副本,它仍然只是“myPackage.myClass”的一个实例。

你混淆了两个不同的概念。

spring中的单词single用于bean作用域,这意味着bean将仅为整个应用程序创建一次。

Singleton通常的含义是指GOF模式。 它是一个面向对象的模式,保证只存在一个类的一个实例(至少在classLoader的范围内)。

以下示例显示了被调用两次的@Bean注释方法:

 @Configuration public class AppConfig { @Bean public ClientService clientService1() { ClientServiceImpl clientService = new ClientServiceImpl(); clientService.setClientDao(clientDao()); return clientService; } @Bean public ClientService clientService2() { ClientServiceImpl clientService = new ClientServiceImpl(); clientService.setClientDao(clientDao()); return clientService; } @Bean public ClientDao clientDao() { return new ClientDaoImpl(); } } 

clientDao()在clientService1()中调用一次,在clientService2()中调用一次。 由于此方法创建了ClientDaoImpl的新实例并将其返回,因此通常需要2个实例(每个服务一个)。 这肯定会有问题:在Spring中,实例化的bean默认具有单例范围。 这就是魔术所带来的:所有@Configuration类在启动时都使用CGLIB进行子类化。 在子类中,子方法在调用父方法并创建新实例之前,首先检查容器是否有任何缓存(作用域)bean。 请注意,从Spring 3.2开始,不再需要将CGLIB添加到类路径中,因为CGLIB类已在org.springframework.cglib下重新打包并直接包含在spring-core JAR中。