Spring中的Bean

Bean的配置

什么是Spring中的Bean?
如果把Spring看做一个大型工厂,则Spring容器中的Bean就是该工厂的产品。要想使用这个工厂生产和管理Bean,就需要在配置文件中告诉它需要哪些Bean,以及需要使用何种方式将这些Bean装配到一起。

小提示:Bean的本质就是Java中的类,而Spring中的Bean其实就是对实体类的引用,来生产Java类对象,从而实现生产和管理Bean。

Spring容器支持两种格式的配置文件,

  1. Properties文件
  2. XML文件

在实际的开发中,最常用的是XML文件格式的配置方式,这种配置方式是通过XML文件来注册并管理Bean之间的依赖关系。

XML配置文件的根元素是<beans>,<beans>中包含了多个<bean>子元素,每一个<bean>子元素定义了一个Bean,并描述了该Bean如何被装配到Spring容器中。关于<beans>元素的常用属性如下表所示:

属性或子元素名称描述
id是一个Bean的唯-标识符, Spring容器对Bean的配置、管理都通过该属性来完成。
nameSpring容器同样可以通过此属性对容器中的Bean进行配置和管理,name属性中可以为Bean 指定多个名称,每个名称之间用逗号或分号隔开。
class该属性指定了Bean的具体实现类,它必须是一个完整的类名,使用类的全限定名。
scope用来设定Bean 实例的作用域,其属性值有: singleton (单例)、prototype ( 原型) request、 session、 global Session、application和websocket。其默认值为singleton。

在配置文件中,通常一个普通的Bean只需要定义id (或name)和class 两个属性即可,定义Bean的方式如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
	<bean id="bean1" class="com.itlv.Bean1"/>
	<bean name="bean2" class="com.itlv.Bean2"/>
</beans>

小提示:如果在Bean中未指定id和name,则Spring 会将class值当作id使用。

Bean实例化

在面向对象的程序中,想要使用某个对象,就需要先实例化这个对象。同样,在Spring中,要想使用容器中的Bean,也需要实例化Bean,实例化Bean有三种方式,分别为构造器实例化、静态工厂方式实例化和实例工厂方式实例化(其中最常用的是构造器实例化)。

构造器实例化是指Spring容器通过Bean对应的类中默认的构造函数来实例化Bean。接下来演示构造器实例化的使用:

  1. 创建Web项目,导入相关Jar包;
  2. 创建名为Bean1的Java类;
  3. 创建Spring配置文件beans1.xml,并配置Bean1实体类Bean;
  4. 创建测试类,测试程序
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
    <bean id="bean1" class="com.ltlv.instance.contrutor.Bean1"/>
</beans>

package com.ltlv.instance.contrutor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class InstanceText1 {
	public static void main(String[] args) {
		// 定义配置文件
		String xmlPath = "com/ltlv/instance/contrutor/beans1.xml";
		// ApplicationContext 在加载配置文件时,对Bean进行实例化
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
		Bean1 bean = (Bean1) applicationContext.getBean("bean1");
		System.out.println(bean);
	}
}

静态工厂是实例化Bean的另一种方式。该方式要求自己创建一个静态工厂的方法来创建Bean的实例。接下来演示静态工厂实例化的使用:

  1. 创建名为Bean2的Java类;
  2. 创建一个Java工厂类,在类中使用静态方法获取Bean2实例;
  3. 创建Spring配置文件beans2.xml,并配置工厂类Bean;
  4. 创建测试类,测试程序;
package com.ltlv.instance.static_factory;
public class MyBean2Factory {
	public static Bean2 createBean(){
		return new Bean2();
	}
}

<bean id="bean2" class="com.ltlv.instance.static_factory.MyBean2Factory" factory-method="createBean" />

package com.ltlv.instance.static_factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class InstanceTest2 {
	public static void main(String[] args) {
		//定义配置文件路径
		String xmlPath = "com/ltlv/instance/static_factory/beans2.xml";
		//applicationContext在加载配置文件,对Bean进行实例化
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
	System.out.println(applicationContext.getBean("bean2"));
	}
}

实例工厂是采用直接创建Bean实例的方式,在配置文件中,通过factory-bean属性配置一个实例工厂,然后使用factory-method属性确定使用工厂中的哪个方法。接下来演示实例工厂实例化的使用:

  1. 创建名为Bean3的Java类;
  2. 创建一个Java工厂类,在类中使用非静态方法获取Bean3实例;
  3. 创建Spring配置文件bean3.xml,并配置工厂类Bean;
  4. 创建测试类,测试程序。
package com.itlv.instance.factory;
public class MyBean3Factory {
	public MyBean3Factory(){
		System.out.println("bean3工厂实例化中");
	}
	public Bean3 createBean(){
		return new Bean3();
	}
}

<!--配置工厂-->
<bean id="myBean3Factory" class="com.itlv.instance.factory.MyBean3Factory"></bean>
<!-- 使用factory-bean属性指向配置的实例工厂,使用factory-method属性确定使用工厂中的那个方法 -->
<bean id="bean3" factory-bean="myBean3Factory" factory-method="createBean"></bean>

package com.itlv.instance.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class InstanceTest3 {
	public static void main(String[] args) {
		//指定配置文件路径
		String xmlPath="com/itlv/instance/factory/bean3.xml";
	//ApplicationContext在加载配置文件时,对Bean进行实例化
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
		System.out.println(applicationContext.getBean("bean3"));
	}
}

作用域种类

作用域名称说明
singleton(单例)使用singleton定义的 Bean在 Spring 容器中将只有一个实例,也就是说,无论有多少个Bean引用它,始终将指向同一个对象。这也是Spring容器默认的作用域。
prototype (原型)每次通过Spring 容器获取的 prototype定义的 Bean时,容器都将创建一个新的Bean实例。
request在一次HTTP请求中,容器会返回该Bean的同一个实例。对不同的HTTP请求则会产生一个新的 Bean,而且该Bean仅在当前HTTP Request内有效。
session在一次HTTP Session中,容器会返回该Bean的同一个实例。对不同的 HTTP请求则会产生一个新的 Bean,而且该Bean仅在当前HTTP Session内有效。
globalSession在一个全局的HTTP Session中,容器会返回该Bean的同一个实例。仅在使用portlet 上下文时有效。
application为每个ServletContext对象创建一个实例。仅在Web相关的ApplicationContext中生效。
websocket为每个websocket对象创建一个实例。仅在Web相关的ApplicationContext中生效。

scope作用域

singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会存在一个共享的Bean实例。singleton作用域对于无会话状态的Bean(如Dao 组件、Service组件)来说,是最理想的选择。

在Spring配置文件中,可以使用<bean>元素的scope属性,将Bean的作用域定义成singleton。

package com.itlv.scope;
public class Scope {
}

<bean id="scope" class="com.itlv.scope.Scope" scope="singleton"></bean>

package com.itlv.scope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class scopeTest {
	public static void main(String[] args) {
		//定义配置文件路径
		String xmlPath ="com/itlv/scope/bean4.xml";
		//加载配置文件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
		//输出获得的实例
		System.out.println(applicationContext.getBean("scope"));
	}
}

prototype作用域

对需要保持会话状态的Bean (如Struts2的Action类)应该使用prototype作用域。在使用prototype作用域时,Spring容器会为每个对该Bean的请求都创建一个新的实例。

在Spring配置文件中,同样使用<bean>元素的scope属性,将Bean的作用域定义成prototype 。

<bean id="scope" class="com.itlv.scope.Scope" scope="prototype"></bean>

Bean生命周期

了解Spring中Bean的生命周期的意义就在于,可以利用Bean在其存活期间的特定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,常会在Bean的postinitiation(初始化后)和predestruction(销毁前)执行一些相关操作。

Spring容器可以管理Bean部分作用域的生命周期。有关说明具体如下:

Bean的生命周期

  1. singleton:Spring容器可以管理singleton作用域的Bean的生命周期,在此作用域下,Spring能够精确的知道该Bean何时被创建,何时初始化完成,以及何时被销毁。
  2. prototype:prototype作用域的Bean,Spring只负责创建,当容器创建了Bean实例后,Bean的实例就交给客户端代码来管理,Spring容器将不再跟踪其生命周期。
    生命周期流程:
    生命周期流程
package com.itlv.Life;
public class Life {
	//构造方法,也就是实例化
	public Life() {
		System.out.println("life start");
	}
	//初试划方法
	private void initMethod() {
		System.out.println("Method start");
	}
	//销毁方法
	private void destroyMethod() {
		System.out.println("destroMethod start");
	}
}

<bean id="life" class="com.itlv.Life.Life" init-method="initMethod" destroy-method="destroyMethod"></bean>

package com.itlv.Life;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class LifeTest {
	public static void main(String[] args) {
		//定义配置文件路径
		String xmlPath = "com/itlv/Life/life.xml";
		//ClassPathXmlApplicationContext在加载配置文件时,对Bean进行实例化
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
		//ClassPathXmlApplicationContext提供了关闭容器的方法,这样bean的销毁方法才会被调用
		context.close();
	}
}

基于XML的装配

Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于注解(Annotation)的装配和自动装配(其中最常用的是基于注解的装配)。

  1. 设置注入(Setter Injection)
    Bean类必须有一个无参构造方法;
    Bean类必须为属性提供setter方法。
    在配置文件中,使用<property>元素来为每个属性注入值。
  2. 构造注入(Constructor Injection)
    Bean类必须提供有参构造方法。
    配置文件中,使用<constructor-arg>元素来为参数注入值。

创建Java类,提供有参,无参构造以及属性setter方法;
创建Spring配置文件beans5.xml,使用2种方式配置Bean;
创建测试类,测试程序。

	/*
	 * 1.使用构造注入
	 * 1.1提供待遇所有参数的有参构造方法
	 */
	public User(String username, Integer password, List<String> list) {
		super();
		this.username = username;
		this.password = password;
		this.list = list;
	}
	/*
	 * 2.使用设置注入
	 * 2.1提供默认空参构造
	 * 2.2为所有属性提供setter方法
	 */
	public User() {
		super();
	}
	
	<!-- 1.使用构造注入方式装配User实例 -->
	<bean id="user1" class="com.itlv.assemble.User">
		<constructor-arg index="0" value="tom" />
		<constructor-arg index="1" value="123456" />
		<constructor-arg index="2">
			<list>
				<value>"contructorvalue1"</value>
				<value>"contructorvalue2"</value>
			</list>
		</constructor-arg>
	</bean>
	<!-- 2.使用设置注入方式装配User实例 -->
	<bean id="user2" class="com.itlv.assemble.User">
		<property name="username" value="张三"></property>
		<property name="password" value="654321"></property>
		<!-- 注入list集合 -->
		<property name="List">
			<list>
				<value>"setlistvalue1"</value>
				<value>"setlistvalue2"</value>
			</list>
		</property>
	</bean>

package com.itlv.assemble;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class XmlBeanAssembleTest {
	public static void main(String[] args) {
		// 定义配置文件路径
		String xmlPath = "com/itlv/assemble/bean5.xml";
		// 加载配置文件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
				xmlPath);
		// 构造方式输出结果
		System.out.println(applicationContext.getBean("user1"));
		// 设置方式输出结果
		System.out.println(applicationContext.getBean("user2"));
	}
}

基于Annotation的装配

基于XM的装配可能会导致XML配置文件过于臃肿,给后续的维护和升级带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。
@Component:用于描述Spring中的Bean,它是一个泛化的概念,仅仅表示一个组件。
@Repository:用于将数据访问层(DAO)的类标识为Spring中的Bean。
@Service:用于将业务层(Service)的类标识为Spring中的Bean。
@Controller:用于将控制层(Controller)的类标识为Spring中的Bean。
@Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。
@Resource:其作用与Autowired一样。@Resource中有两个重要属性: name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。
@Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。

创建接口UserDao,并定义方法;
创建接口实现类UserDaoImpl,用@Repository声明类;
创建接口UserService,并定义方法;
创建接口实现类UserServiceImpl,用@Service声明类,并使用@Resource注入UserDao属性;
创建控制器类,用@Controller声明,并使用@Resource注入UserService属性;
创建Spring配置文件,配置Bean;
创建测试类,测试程序。

@Repository("userDao")
public class UserDaoImpl implements UserDao {
	@Override
	public void save() {
		// TODO Auto-generated method stub
		System.out.println("userdao...save...");
	}
}

@Service("userService")
public class UserServiceImpl implements UserService {
	@Resource(name = "userDao")
	private UserDao userDao;
	@Override
	public void save() {
		// 调用userDao中的save()方法
		this.userDao.save();
		System.out.println("userservice...save...");
	}
}

@Controller("userController")
public class UserController {
	@Resource(name="userService")
	private UserService userService;
	public void save(){
		this.userService.save();
		System.out.println("userController...save...");
	}
}

<context:annotation-config/>
<bean id="userDao" class="com.itlv.annotation.UserDaoImpl"></bean>
<bean id="userService" class="com.itlv.annotation.UserServiceImpl"></bean>
<bean id="userController" class="com.itlv.annotation.UserController"></bean>

public class AnnotationAssembleTest {
	public static void main(String[] args) {
		//定义配置文件路径
		String xmlPath = "com/itlv/annotation/bean6.xml";
		//加载配置文件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
		//获取UserController实例
		UserController userController =(UserController) applicationContext.getBean("userController");
		//调用UserController中的save()方法
		userController.save();	
	}
}

<context:component-scan base-package="com.itlv.annotation"/>

自动装配

所谓自动装配,就是将一个Bean自动的注入到到其他Bean的Property中。Spring的bean元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。autowire属性有5个值,其值及说明下表所示:

属性值说明
default(默认值)由<bean>的上级标签<beans>的 default-autowire属性值确定。例如<beansdefault-autowire=“byName”>,则该<bean>元素中的autowire 属性对应的属性值就为byName 。
byName根据属性的名称自动装配。容器将根据名称查找与属性完全一致的Bean,并将其属性自动装配。
byType根据属性的数据类型(Type)自动装配,如果一个Bean的数据类型,兼容另一个Bean中属性的数据类型,则自动装配。
constructor根据构造函数参数的数据类型,进行byType模式的自动装配。
no默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义。

修改上一节UserServiceImpl和UserController,分别增加类属性的setter方法;
修改Spring配置文件,使用autowire属性配置Bean;
重新测试程序。

<bean id="userDao" class="com.itlv.annotation.UserDaoImpl"></bean>
<bean id="userService" class="com.itlv.annotation.UserServiceImpl" autowire="byName"/>
<bean id="userController" class="com.itlv.annotation.UserController" autowire="byName"></bean>

本章对Spring的Bean进行了详细讲解,首先介绍了Bean的配置,然后通过案例讲解了Bean实例化的三种方式,接下来介绍了Bean的作用域和生命周期,最后讲解了Bean的三种装配方式。
通过本章的学习,要求读者了解Bean的装配过程,并能使用Bean的装配进行开发。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值