Spring中的Bean
Spring其实就是一个大型的工厂,而Spring容器中的Bean就是该工厂的产品.对于Spring容器能够生产那些产品,则取决于配置文件中配置。对于我们而言,我们使用Spring框架所做的就是两件事:开发Bean、配置Bean。对于Spring矿建来说,它要做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法完成“依赖注入”。
Bean的定义
<beans…/>元素是Spring配置文件的根元素,<bean…/>元素师<beans…/>元素的子元素,<beans…/>元素可以包含多个<bean…/>子元素,每个<bean…/>元素可以定义一个Bean实例,每一个Bean对应Spring容器里的一个Java实例定义Bean时通常需要指定两个属性。
Id:确定该Bean的唯一标识符,容器对Bean管理、访问、以及该Bean的依赖关系,都通过该属性完成。Bean的id属性在Spring容器中是唯一的。
Class:指定该Bean的具体实现类。注意这里不能使接口。通常情况下,Spring会直接使用new关键字创建该Bean的实例,因此,这里必须提供Bean实现类的类名。
下面是定义一个Bean的简单配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 使用id属性定义bean1 其对应的实现类为com.Bean1 -->
<bean id="bean1" class="com.Bean1" />
<!-- 使用name属性定义bean1 其对应的实现类为com.Bean1 -->
<bean id="bean2" class="com.Bean2" />
Bean的实例化
在面向对象的程序中,想要使用某个对象,就需要先实例化这个对象。同样在Spring中,要想使用容器中的Bean,也需要实例化Bean。实例化Bean有三种方式,分别为构造器实例化、静态工厂方法实例化,和实例工厂方式实例化(其中最常用的是构造器实例化)。
构造器实例化
构造器实例化时指Spring容器通过Bean对应类中默认对无参构造方法来实例化Bean,下面通过一个案例演示Spring 容器是如何通过构造器来实例化Bean的
public class Bean1 {
}
创建配置文件beans1.xml
<?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.gouzaoqi.shilihua.Bean1" />
</beans>
创建测试类
package com.gouzaoqi.shilihua;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class gouzaoTest {
public static void main(String[] args) {
//定义配置文件路径
String xmlPath="com/gouzaoqi/shilihua/beans1.xml";
//ApplicationContext在加在配置文件时,对Bean进行实例化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
Bean1 bean = (Bean1) applicationContext.getBean("bean1");
System.out.println(bean);
}
}
上面首先定义了文件的路径,然后Spring容器ApplicationContext会加在配置文件。在加载时,Spring容器会通过Id为bean1对实现类Bean1中默认对无参构造方法对Bean进行实例化
运行得到输出结果Spring容器已成功实例化了Bean1
静态工厂方式实例化
使用静态工厂是实例化Bean对另一种方式。改方式要求开发者创建一个静态工厂的方法来创建Bean的实例,其Bean配置中对Class属性所指定的不再是Bean实例化的实现类,而是静态工厂类同时还需要使用factory-method属性来指定所创建对静态
工厂方法。 下面通过一个案例来了解一下。
1.创建一个Bean2类,该类与Bean1一样,不需添加任何方法
2.创建一个MyBean2Facyory类,并在类中创建一个静态方法createBean()来返回Bean2实例
public class MyBean2Factory {
//使用自己对工场创建Bean2实例
public static Bean2 createBean() {
return new Bean2();
}
}
创建Spring配置文件beans2
<?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后,Spring容器不知道哪个是所需要对工厂方法,
所以增加factory-method属性来告诉Spring容器,其方法名称为createBean -->
<bean id="bean2" class="com.jintaigc.shilihua.MyBean2Factory" factory-method="createBean" />
</beans>
创建测试类
package com.jintaigc.shilihua;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class gongchangTest {
public static void main(String[] args) {
String xmlPath="com/jintaigc/shilihua/beans2.xml";
//ApplicationContext在加在配置文件时,对Bean进行实例化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
System.out.println(applicationContext.getBean("bean2"));
}
}
运行程序输出结果
执行程序后,可以看到使用自定义对静态工厂方法,已经被实例化了Bean2.
实例化工厂方式实例化
还有一种实例化Bean的方式就是采用实例工厂。此方法的工厂类中,不再使用静态方法创建Bean实例,而是采用直接创建Bean实例对方式。同时,在配置文件中,需要实例化对Bean也不是通过calss属性直接指向对实例化类,而是通过factory-bean属性指向配置对实例工厂,然后使用factory-method属性确定使用工厂中对哪个方法。下面通过案例来看
1.创建一个Bean3类,该类与Bean1一样,不需添加任何方法
2.创建工厂类MyBean3Facyory类,在类中使用默认无参构造方法输出“bean3工厂实例化中”语句,并使用createBean()方法创建Bean3对象
package com.shiligongchang.shilihua;
public class MyBean3Factory {
public MyBean3Factory() {
System.out.println("bean3工厂实例化中");
}
//创建Bean3实例方法
public Bean3 createBean() {
return new Bean3();
}
}
创建Spring配置文件beans3
<?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="myBean3Factory" class="com.shiligongchang.shilihua.MyBean3Factory" />
<!-- 使用factory-bean属性指向配置实例工厂,
使用factory-method属性确定使用工厂中对哪个方法 -->
<bean id="bean3" factory-bean="myBean3Factory" factory-method="createBean" />
</beans>
在上述配置文件中,首先配置了一个工厂Bean,然后配置了需要实例化对Bean。在id为bean3对Bean中,使用factory-bean属性指向配置的实例工厂,该属性值就是工厂Bean的id。使用factory-method属性来确定使用工厂中对createBean()方法。
创建测试类
package com.shiligongchang.shilihua;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class shiligongcTest {
public static void main(String[] args) {
String xmlPath="com/shiligongchang/shilihua/beans3.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
System.out.println(applicationContext.getBean("bean3"));
}
}
运行程序输出结果
可有看到,使用实例化工厂对方式,同样成功实例化了Bean3
Bean的作用域
singleton作用域与prototype作用域
singleton是Spring容器默认对作用域,当Bean对作用域为singleton时,Spring容器就只会存在一个共享对Bean实例。singleton作用域对于无会话状态对Bean(如Dao组件、Service组件)来说,是最理想对选择。
对需要保持会话状态对Bean(如Struts2对Action类)应该使用prototype作用域。在使用prototype作用域时,Spring容器会为每个对该Bean对请求都创建一个新对实例。
1.创建一个无参构造方法
2.Spring配置文件
<?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">
<!-- singleton作用域 -->
<!-- <bean id="scope" class="com.singleton.zuoyongyu.Scope" scope="singleton" /> -->
<!-- prototype作用域 -->
<bean id="scope" class="com.singleton.zuoyongyu.Scope" scope="prototype" />
</beans>
输出结果分别为
singleton作用域
prototype作用域
Bean的生命周期
了解Spring中Bena对生命周期对意义就在于,可以利用Bean在其存活期间对特定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,常会在Bean对postinitiation(初始化后)和predestruction(销毁前)执行一些相关操作。
简单对演示代码
三个方法对应每句话
package com.bean.smzhouqi;
public class Life {
//构造方法,也就是实例化
public Life() {
System.out.println("life start");
}
//初始化方法
public void shuchihua(){
System.out.println("chushihua star");
}
//销毁方法
public void xiaohui() {
System.out.println("xiaohui star");
}
}
Spring配置文件
<?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">
<!-- scope="singleton"这个值是默认,在默认情况下spring能够全程跟踪bean的生命周期 -->
<bean id="life" class="com.bean.smzhouqi.Life" init-method="shuchihua"
destroy-method="xiaohui" />
</beans>
创建测试文件
package com.bean.smzhouqi;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestLife {
public static void main(String[] args) {
String xmlPath = "com/bean/smzhouqi/life.xml";
//ClassPathXmlApplicationContext 在加载配置文件时,对Bean进行实例化
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
//ClassPathXmlApplicationContext 提供了关闭容器的方法,这样bean的销毁方法才会被停用
context.close();
}
}
运行得到结果
可以看到方法都出来了
Bean的装配方式
基于XML的装配
Spring提供了两种装配方式:设值注入(Setter Injection)和构造注入(Constructor Injection)下面讲解如何在XML配置文件中使用这两种注入方式实现基于XML的装配。
在该包中创建User类,并在类中定义username,password和list集合三个属性及对应的setter方法
package com.bean.zhuangpei;
import java.util.List;
public class User {
private String username;
private Integer password;
private List<String>list;
/*
*1.使用构造注入
* 1.1提供带所有参数的有参构造方法
*/
public User(String username, Integer password, List<String> list) {
super();
this.username = username;
this.password = password;
this.list = list;
}
public User() {
super();
}
/*
* 2.使用设值注入
* 2.1提供默认空参构造方法;
* 2.2为所有属性提供setter方法。
*/
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getPassword() {
return password;
}
public void setPassword(Integer password) {
this.password = password;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", list=" + list + "]";
}
}
创建配置文件
<?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">
<!-- 1.使用构造注入方式装配User实例 -->
<bean id="user1" class="com.bean.zhuangpei.User">
<constructor-arg index="0" value="ysw" />
<constructor-arg index="1" value="123456" />
<constructor-arg index="2">
<list>
<value>"constructorvalue1"</value>
<value>"constructorvalue2"</value>
</list>
</constructor-arg>
</bean>
<!-- 2.使用设值注入方式装配User实例 -->
<bean id="user2" class="com.bean.zhuangpei.User">
<property name="username" value="娇娇"></property>
<property name="password" value="5201314"></property>
<!-- 注入list集合 -->
<property name="list">
<list>
<value>"setlistvalue1"</value>
<value>"setlistvalue2"</value>
</list>
</property>
</bean>
</beans>
创建测试文件
package com.bean.zhuangpei;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class xmlBeanAssembleTest {
public static void main(String[] args) {
//定义配置文件路径
String xmlPath = "com/bean/zhuangpei/beans5.xml";
//加载配置文件
ApplicationContext applicationContext= new ClassPathXmlApplicationContext(xmlPath);
//构造方法输出结果
System.out.println(applicationContext.getBean("user1"));
//设值方法输出结果
System.out.println(applicationContext.getBean("user2"));
}
}
得到输出结果
读黑马程序员《Java EE企业级 应用开发教程》