前言
我们知道,容器是一个空间的概念,一般理解为可盛放物体的地方。在Spring容器通常理解为BeanFactory或者ApplicationContext。我们知道spring的IOC容器能够帮我们创建对象,对象交给spring管理之后我们就不用手动去new对象。
那么Spring是如何管理Bean的呢?
文章目录
- 前言
- 一、概念
- 二、创建Bean对象的三种方式
- 2.1、使用默认构造函数创建方式
- 2.1.1、定义Bean
- 2.1.2、主配置文件中配置bean
- 2.1.3、测试Bean
- 2.1.4、注意点
- 2.2、使用工厂中的实例方法创建方式
- 2.2.1、定义工厂
- 2.2.2、定义Bean
- 2.2.3、主配置文件中配置Bean
- 2.2.4、测试
- 2.3、使用工厂中的静态方法创建方式
- 2.3.1、定义工厂
- 2.3.2、定义Bean
- 2.3.3、主配置文件中配置Bean
- 2.3.4、测试
- 三、Bean对象的作用域
- 3.1、说明
- 3.2、作用域类型
- 3.3、注意细节
- 3.4、如何修改Bean的作用域
- 3.5、测试
- 3.5.1、测试singleton单例
- 3.5.2、测试prototype多例
- 四、Bean对象的生命周期
- 4.1、单例对象
- 4.1.1、说明
- 4.1.2、测试
- 4.1.2.1、定义Bean
- 4.1.2.2、主配置文件中配置Bean
- 4.1.2.3、测试
- 4.1.2.4、测试结果
- 4.2、多例对象
- 4.2.1、说明
- 4.2.2、测试
- 4.2.2.1、定义Bean
- 4.2.2.2、主配置文件中配置Bean
- 4.2.2.3、测试1
- 4.2.2.4、测试2
- 五、总结
一、概念
简而言之,Spring bean是Spring框架在运行时管理的对象。Spring bean是任何Spring应用程序的基本构建块。你编写的大多数应用程序逻辑代码都将放在Spring bean中。
Spring bean的管理包括:
- 创建一个对象
- 提供依赖项(例如其他bean,配置属性)
- 拦截对象方法调用以提供额外的框架功能
- 销毁一个对象
Spring bean是框架的基本概念。作为Spring的用户,你应该对这个核心抽象有深刻的理解。
二、创建Bean对象的三种方式
2.1、使用默认构造函数创建方式
2.1.1、定义Bean
public class UserServiceImpl {
}
2.1.2、主配置文件中配置bean
<!-- 方式一:使用默认构造函数方式创建Bean -->
<beans>
<bean id="userService" class="cn.bdqn.UserServiceImpl"></bean>
</beans>
2.1.3、测试Bean
@Test
public void testUserService() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
// 2、从容器中根据id获取对象(bean)
UserServiceImpl userService = (UserServiceImpl) ac.getBean("userService");
// 3、打印bean
System.out.println(userService);
}
2.1.4、注意点
此种方式采用的就是通过默认构造函数的方式创建Bean,假设我们给UserServiceImpl添加了一个带参的构造方法,则运行会报错,原因在于当我们为某个类自定义构造方法的时候,Java编译器便不会为该类提供默认的不带参数的构造方法了。
2.2、使用工厂中的实例方法创建方式
2.2.1、定义工厂
// UserService的工厂,作用是创建UserServiceBean对象
public class UserServiceImplFactory {
public UserServiceImpl createUserService(){
return new UserServiceImpl();
}
}
2.2.2、定义Bean
public class UserServiceImpl {
}
2.2.3、主配置文件中配置Bean
<beans>
<!-- 方式二:使用工厂中提供的实例方法创建Bean -->
<!-- 第一步:把该工厂定义出来 -->
<bean id="userServiceFactory" class="cn.bdqn.UserServiceImplFactory"/>
<!-- 第二步:定义Bean(通过userServiceFactory中提供的实例方法)-->
<bean id="userService" factory-bean="userServiceFactory"
factory-method="createUserService"/>
</beans>
2.2.4、测试
@Test
public void testUserService() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
// 2、从容器中根据id获取对象(bean)
UserServiceImpl userService = (UserServiceImpl) ac.getBean("userService");
// 3、打印bean
System.out.println(userService);
}
2.3、使用工厂中的静态方法创建方式
2.3.1、定义工厂
// UserService的工厂,作用是创建UserServiceBean对象
public class UserServiceImplFactory {
public static UserServiceImpl createUserService(){
return new UserServiceImpl();
}
}
2.3.2、定义Bean
public class UserServiceImpl {
}
2.3.3、主配置文件中配置Bean
<beans>
<!-- 方式三:使用工厂中提供的静态方法创建Bean -->
<!-- 定义Bean(通过工厂类的静态方法创建) -->
<bean id="userService" class="cn.bdqn.UserServiceImplFactory"
factory-method="createUserService">
</bean>
</beans>
2.3.4、测试
@Test
public void testUserService() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
// 2、从容器中根据id获取对象(bean)
UserServiceImpl userService = (UserServiceImpl) ac.getBean("userService");
// 3、打印bean
System.out.println(userService);
}
三、Bean对象的作用域
3.1、说明
Spring对Bean的默认的作用域(作用范围)是singleton【单例】
3.2、作用域类型
-
singleton:单例的(默认值),只会new一次。
-
prototype:多例的,用到一次就会new一次。
-
request:作用于web应用的请求范围,Spring创建这个类之后,将这个类存到request范围内。
-
session:应用于web项目的会话范围,Spring创建这个类之后,将这个类存到session范围内。
-
global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session。
3.3、注意细节
实际开发中用得最多的就是singleton和prototype,在整合struts2的时候使用prototype,在整合SpringMVC的时候使用singleton。
3.4、如何修改Bean的作用域
bean标签的scope属性,作用:指定bean的作用范围。
3.5、测试
3.5.1、测试singleton单例
public class UserServiceImpl {
}
<beans>
<bean id="userService" class="cn.bdqn.UserServiceImpl" />
</beans>
@Test
public void testUserService() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
// 2、从容器中根据id获取对象(bean)
UserServiceImpl userService1 = (UserServiceImpl) ac.getBean("userService");
UserServiceImpl userService2 = (UserServiceImpl) ac.getBean("userService");
// 3、打印bean
System.out.println(userService1 == userService2); // true
}
3.5.2、测试prototype多例
public class UserServiceImpl {
}
<bean id="userService" class="cn.bdqn.UserServiceImpl" scope="prototype"/>
@Test
public void testUserService() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
// 2、从容器中根据id获取对象(bean)
UserServiceImpl userService1 = (UserServiceImpl) ac.getBean("userService");
UserServiceImpl userService2 = (UserServiceImpl) ac.getBean("userService");
// 3、打印bean
System.out.println(userService1 == userService2); // false
}
四、Bean对象的生命周期
4.1、单例对象
4.1.1、说明
出生:当容器创建时对象出生
活着:只要容器还在,对象一直活着
死亡:容器销毁,对象消亡
4.1.2、测试
4.1.2.1、定义Bean
public class UserServiceImpl {
public UserServiceImpl(){
System.out.println("对象的构造方法执行了");
}
public void init(){
System.out.println("对象初始化了");
}
public void destroy(){
System.out.println("对象销毁了");
}
}
4.1.2.2、主配置文件中配置Bean
<beans>
<bean id="userService" class="cn.bdqn.UserServiceImpl"
scope="singleton" init-method="init" destroy-method="destroy"/>
</beans>
4.1.2.3、测试
@Test
public void testUserService() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
ac.close();
}
// 结果:对于单例对象来说,只要容器创建了,那么对象就创建了。类似于立即加载。
4.1.2.4、测试结果
对象的构造方法执行了
对象初始化了
对象销毁了
总结:单例对象的生命周期和容器相同
4.2、多例对象
4.2.1、说明
出生:当我们使用对象时spring框架为我们创建
活着:对象只要是在使用过程中就一直活着。
死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
4.2.2、测试
4.2.2.1、定义Bean
public class UserServiceImpl {
public UserServiceImpl(){
System.out.println("对象的构造方法执行了");
}
public void init(){
System.out.println("对象初始化了");
}
public void destroy(){
System.out.println("对象销毁了");
}
}
4.2.2.2、主配置文件中配置Bean
<beans>
<bean id="userService" class="cn.bdqn.UserServiceImpl"
scope="prototype" init-method="init" destroy-method="destroy"/>
</beans>
4.2.2.3、测试1
@Test
public void testUserService() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
ac.close();
}
// 结果:什么都不输出,说明容器启动的时候,对于多例对象来说并不会创建
4.2.2.4、测试2
@Test
public void testUserService() throws Exception{
// 1、读取主配置文件信息,获取核心容器对象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl userService = (UserServiceImpl) ac.getBean("userService");
System.out.println(userService);
ac.close();
}
/**
结果:
对象的构造方法执行了
对象初始化了
说明:
对于多例对象来说,只有等到真正使用到该对象的时候才会创建。类似于懒加载。
**/
对于多例的Bean,Spring框架是不负责管理的
五、总结