Spring2.x中设置Bean的作用域

简介: 在配置文件里声明的Bean时,实际定义的并不是一个Bean实例,而是为Bean创建了一个模板,当通过getBean()调用或其他请求改Bean的时候,Spring将根据Bean的实际作用域返回Bean的实例,在某些情况下默认的作用域并不适合,此时需要为Bean设置一个更适合的作用域。

 
在配置文件里声明的Bean时,实际定义的并不是一个Bean实例,而是为Bean创建了一个模板,当通过getBean()调用或其他请求改Bean的时候,Spring将根据Bean的实际作用域返回Bean的实例,在某些情况下默认的作用域并不适合,此时需要为Bean设置一个更适合的作用域。

在Spring2.x里,可以通过<bean>中的scope属性设置作用域,默认情况下Spring只为在Ioc容器里声明的Bean创建一个实例,整个Ioc范围内都共享这个实例,所有后续的getBean()调用和引用该实例,都将返回这个唯一的Bean实例。这个作用域称为singleton,是默认的作用域。

Spring2.x中Bean的几种作用域:

1、singleton--------------为每个Spring Ioc容器创建一个Bean实例;

2、prototype-------------每次请求时都创建一个新的实例;

3、request---------------每个HTTP请求创建一个Bean实例,这个作用域仅在WEB应用程序的上下文中有效;

4、session---------------每个HTTP请求创建一个Bean实例,这个作用域仅在WEB应用程序的上下文中有效;

5、globalSession------为每个全局的HTTP会话创建一个Bean实例,这个作用域尽在门户应用程序的上下文中有效;

下边将用一个商品购物车例子来说明这个Bean的实例作用域:

package com.song.spring.scope;

public abstract class Product {

	private String name;
	private double price;
	
	public Product(){}
	
	public Product(String name, double price){
		this.name = name;
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}
	
	public String toString(){
		return name + " " + price;
	}
}

package com.song.spring.scope;

public class Battery extends Product {

	private boolean rechargeable;
	
	public Battery(){
		super();
	}
	
	public Battery(String name, double price){
		super(name, price);
	}

	public boolean isRechargeable() {
		return rechargeable;
	}

	public void setRechargeable(boolean rechargeable) {
		this.rechargeable = rechargeable;
	}
	
	
}

package com.song.spring.scope;

public class Disc extends Product {

	private int capacity;
	
	public Disc(){
		super();
	}
	
	public Disc(String name, double price){
		super(name, price);
	}

	public int getCapacity() {
		return capacity;
	}

	public void setCapacity(int capacity) {
		this.capacity = capacity;
	}
	
	
}

接下来创建一个无购物车实例;

package com.song.spring.scope;

import java.util.ArrayList;
import java.util.List;

public class ShoppingCart {

	private List<Product> items = new ArrayList<Product>();
	
	public void addItem(Product item){
		items.add(item);
	}
	
	public List<Product> getItem(){
		return items;
	}
}

在classpath:下的xml文件applicationContext.xml中的Bean配置为:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
        "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>    
	<bean id="aaa" class="com.song.spring.scope.Battery">
		<property name="name" value="AAA" />
		<property name="price" value="2.5" />
	</bean>
	
	<bean id="cdrw" class="com.song.spring.scope.Disc">
		<property name="name" value="CD-RW" />
		<property name="price" value="1.5" />
	</bean>
	
	<bean id="dvdrw" class="com.song.spring.scope.Disc">
		<property name="name" value="DVD-RW" />
		<property name="price" value="3.0" />
	</bean>
	
	<bean id="shoppingCart" class="com.song.spring.scope.ShoppingCart" />
</beans>

创建一个运行类:

package com.song.spring.scope;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {

		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		Product aaa = (Product)context.getBean("aaa");
		Product cdrw = (Product)context.getBean("cdrw");
		Product dvdrw = (Product)context.getBean("dvdrw");
		
		ShoppingCart cart1 = (ShoppingCart)context.getBean("shoppingCart");
		cart1.addItem(aaa);
		cart1.addItem(cdrw);
		System.out.println("Shopping Cart1 contains:" + cart1.getItem());
		
		ShoppingCart cart2 = (ShoppingCart)context.getBean("shoppingCart");
		cart2.addItem(dvdrw);
		System.out.println("Shopping Cart2 contains:" + cart2.getItem());
	}

}
运行结果为:

Shopping Cart1 contains:[AAA 2.5, CD-RW 1.5]
Shopping Cart2 contains:[AAA 2.5, CD-RW 1.5, DVD-RW 3.0]

显然这不是我们想要的结果;我们所要的是每个顾客各获得一个Bean实例,这时就应该将配置文件中的Bean实例的作用域改为prototype;

<bean id="shoppingCart" class="com.song.spring.scope.ShoppingCart" scope="prototype"/>


再运行所得结果为:

Shopping Cart1 contains:[AAA 2.5, CD-RW 1.5]
Shopping Cart2 contains:[DVD-RW 3.0]

这才是我们想要的结果,完毕!


目录
相关文章
|
8月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
516 26
|
10月前
|
XML 安全 Java
|
10月前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
184 12
|
10月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
233 12
|
10月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
264 6
|
10月前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
427 4
|
11月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
580 4
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
10月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
185 1
|
12月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
194 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
12月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。