Spring注解驱动开发 第三节组件的单实例与多实例
spring的只要是注入到容器中的默认都是单实例的,我们可以做一个小实验测试一下
@Configuration
public class MainConfig2 {
/**
* @see
* ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
*/
//@Scope("prototype")
@Bean
public Person person(){
return new Person("张三","27");
}
}
新建了一个MainConfig2配置文件,然后将person注入到spring容器中。
@Test
public void test02(){
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
Person person1 = (Person) context.getBean("person");
Person person2 = (Person) context.getBean("person");
System.out.println(person1 == person2);
}
由于spring默认单实例,所以当两次拿到的person时同一个,所以结果为true,下面查看打印结果:
四月 22, 2019 3:19:11 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Mon Apr 22 15:19:11 GMT+08:00 2019]; root of context hierarchy
true
Process finished with exit code 0
果不其然,确实是true,这也证实了spring默认时单实例的。当我再次修改代码,验证spring在单实例的情况下,组件的加载方式是怎样的。
/**
* @see
* ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
*/
//@Scope("prototype")
@Bean
public Person person(){
System.out.println("person类被初始化了...");
return new Person("张三","27");
}
@Test
public void test02(){
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
// System.out.println("spring容器初始化完成");
//
// Person person1 = (Person) context.getBean("person");
// Person person2 = (Person) context.getBean("person");
//
// System.out.println(person1 == person2);
}
结果:
四月 22, 2019 3:23:50 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Mon Apr 22 15:23:50 GMT+08:00 2019]; root of context hierarchy
person类被初始化了...
Process finished with exit code 0
可以看出,在测试类中,我们只是加载了一下配置类,启动了spring容器,然后这个类就被注入到spring容器中了,在这种场景下,基本可以断定,在spring单实例模式的情况下,在启动spring容器的时候就开始加载类成为spring的组件,以后在从容器中获取实例时都是这个对象,所以每次获取他们都是同一个对象。
多实例实验
/**
* @see
* ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
*/
@Scope("prototype")
@Bean
public Person person(){
System.out.println("person类被初始化了...");
return new Person("张三","27");
}
@Test
public void test02(){
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
System.out.println("spring容器初始化完成");
Person person1 = (Person) context.getBean("person");
Person person2 = (Person) context.getBean("person");
System.out.println(person1 == person2);
}
结果:
四月 22, 2019 3:31:39 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Mon Apr 22 15:31:39 GMT+08:00 2019]; root of context hierarchy
spring容器初始化完成
person类被初始化了...
person类被初始化了...
false
Process finished with exit code 0
可以看出当在组件中加入@Scope(“prototype”)后,spring容器对这个组件就改为多实例的方式,从容器中取出的两个person不是一个对象。所以打印false,然后我们仔细观察一下打印结果的内容,spring容器初始化完成时测试类中的打印语句,所以在启动spring后bean并没有被注入到容器,与单实例完全相反,在getBean的时候才初始化了一个person类,而且每次getBean都会初始化一个person对象,所以他是new了多次的,对比的话肯定不是一个对象,所以返回false。
总结:单实例在启动spring时创建对象,注入到容器,以后获取这个bean都是同一个bean
多实例在启动spring时不创建对象,也不注入容器,获取bean时财创建一个对象并返回,而且每次获取一个对象都会创建一个新的对象
下面在说一说懒加载
@Lazy
@Bean
public Person person(){
System.out.println("person类被初始化了...");
return new Person("张三","27");
}
加入注解@Lazy就可使这个类懒加载到spring容器中。我们查看一下打印结果:
四月 22, 2019 3:45:24 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Mon Apr 22 15:45:24 GMT+08:00 2019]; root of context hierarchy
spring容器初始化完成
person类被初始化了...
true
Process finished with exit code 0
分析结果:首先在容器启动后我们并未看到person类被加载到容器,而是在getBean的时候才被加载到容器,但是这个person只被加载了一次,最后对比两次获取的person,结果是true,表示他们获取的是同一个对象。
本文深入探讨了Spring框架中组件的单实例与多实例特性。通过实验演示了单实例模式下,组件在Spring容器启动时即被加载并保持唯一;而在多实例模式下,每次请求都会创建新的组件实例。此外,还介绍了懒加载机制如何延迟组件的初始化。
344

被折叠的 条评论
为什么被折叠?



