在默认情况下,Spring应用上下文中所有的bean都是以单例(singleton)的形式创建的,即不管给定的一个bean被注入到其他bean多少次,每次所注入的都是同一个实例。
Spring定义了多种作用域,可以基于这些作用域创建bean:
单例是默认的作用域,如果要使用其它的作用域创建bean,需要使用 @Scope
注解,该注解可以和 @Component
, @Service
, @Bean
等注解一起使用。
为了更好的理解,我们通过具体的代码示例来理解下Singleton与ProtoType的区别。
package chapter03.scope; import org.springframework.stereotype.Service; @Service public class DemoSingletonService { } 复制代码
因为Spring默认配置的Scope是Singleton,因此以上代码等价于以下代码:
package chapter03.scope; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @Service @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) public class DemoSingletonService { } 复制代码
上面的代码也可以写成 @Scope("singleton")
。
如果是自动装配bean,语法为:
package chapter03.scope; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @Service @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class DemoPrototypeService { } 复制代码
上面的代码也可以写成 @Scope("prototype")
。
如果是在Java配置类中声明bean,语法为:
@Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public DemoPrototypeService demoPrototypeService() { return new DemoPrototypeService(); } 复制代码
如果是在xml中声明bean,语法为:
<bean id="demoPrototypeService" class="chapter03.scope.DemoPrototypeService" scope="prototype"/> 复制代码
package chapter03.scope; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("chapter03.scope") public class ScopeConfig { } 复制代码
新建一个Main类,在main()方法中,分别从Spring容器中获取2次Bean,然后判断Bean的实例是否相等:
package chapter03.scope; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScopeConfig.class); DemoSingletonService s1 = context.getBean(DemoSingletonService.class); DemoSingletonService s2 = context.getBean(DemoSingletonService.class); DemoPrototypeService p1 = context.getBean(DemoPrototypeService.class); DemoPrototypeService p2 = context.getBean(DemoPrototypeService.class); System.out.println("s1 与 s2 是否相等:" + s1.equals(s2)); System.out.println("p1 与 p2 是否相等:" + p1.equals(p2)); context.close(); } } 复制代码
运行结果如下:
从运行结果也可以看出,默认情况下即Singleton类型的Bean,不管调用多少次,只会创建一个实例。
即使是大小写不一致也不行,如我们将DemoPrototypeService类的代码修改为:
package chapter03.scope; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @Service @Scope("PROTOTYPE") public class DemoPrototypeService { } 复制代码
此时运行代码,就会报错:
源码地址: github.com/zwwhnly/spr… ,欢迎下载。
汪云飞《Java EE开发的颠覆者:Spring Boot实战》
打个小广告,欢迎扫码关注微信公众号:「申城异乡人」,定期分享Java技术干货,让我们一起进步。