Bean对象是由BeanFactory创建的,而Bean对象在BeanFactory中有几种不同的作用域。
-
singleton:单例模式,在不配置作用域的默认情况下Spring自动使用单例实现。每次拿到的都是同一个变量,因为bean对象在IOC容器中只有单独一份!
-
prototype:原型模式,底层使用原型设计模式实现,每次获取到的实例对象都是不同的。
-
request:Web中的一次完整的请求
-
session:Web应用中的一次完整的会话。
1. 单例模式
创建User实体类
public class User {
private String name;
public User(){
System.out.println("User无参构造函数");
}
public void setName(String name) {
this.name = name;
}
}
1.1、饿汉式加载(不启用懒加载)
Bean对象默认情况下是单例的,也就是说每次获取的都是同一个实例对象。并且默认情况下在读取配置文件的时候就会将对象进行加载初始化。
<!-- 1. 单例模式未启用懒加载 test1 -->
<bean id="user" class="com.pojo.User" scope="singleton">
<property name="name" value="小明"/>
</bean>
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("===============配置文件加载完毕==============");
User user1 = context.getBean("user", User.class);
User user2 = context.getBean("user", User.class);
System.out.println("user1 = " + user1);
System.out.println("user2 = " + user2);
}
可以看到单例模式下在加载完配置文件的时候,bean对象就已经创建完毕。并且多次获取的对象都是来自同一个地址!
1.2、启用懒加载
启用懒加载需要在bean对象的xml配置lazy-init = “true”;现在单例的情况下不会再加载配置文件的时候就进行加载,而是在第一次获取对象的时候IOC容器才会进行单例对象的创建!
<!-- 2. 单例模式启用懒加载 test2 -->
<bean id="user" class="com.pojo.User" scope="singleton" lazy-init="true">
<property name="name" value="小明"/>
</bean>
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("===============配置文件加载完毕==============");
User user1 = context.getBean("user", User.class);
User user2 = context.getBean("user", User.class);
System.out.println("user1 = " + user1);
System.out.println("user2 = " + user2);
}
懒加载需要注意的是,当一个对象A依赖对象B时,如果A未启用懒加载而B启用了懒加载,那么读取xml配置文件的时候B的懒加载失效!
2. 原型模式
-
prototype:多实例对象,与单例不同的不仅仅是创建对象的方式;而且创建的时间也不相同。
-
singleton不启用懒加载的情况下,在读取xml配置文件的时候bean对象就已经生成。
-
prototype是在调用getBean方法时候创建对象。
-
虽然prototype是多例的,每次获取的对象都是不同的前提:保证每次都是getBean从容器中获取!
<!-- 3. 原型模式 test3 -->
<bean id="user" class="com.pojo.User" scope="prototype">
<property name="name" value="小明"/>
</bean>
@Test
public void test3(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("===============配置文件加载完毕==============");
User user1 = context.getBean("user", User.class);
System.out.println("user1 = " + user1);
User user2 = context.getBean("user", User.class);
System.out.println("user2 = " + user2);
}
3. bean的生命周期
生命周期:对象从创建到销毁的过程!
bean的生命周期分为五部分:
-
通过无参构造创建bean的实例
-
使用set方式进行依赖注入
-
执行初始化方法,需要手动配置。
-
getBean获取实例对象
-
最后关闭context上下文对象时,销毁bean(需要配置销毁方法)。
- 其中前三个步骤顺序是固定的,但是加载的时间是不固定的。这与配置是否单例还是原型、是否延迟加载都有关系。
public class Person {
private String name;
public Person(){
System.out.println("第一步 执行无参构造创建bean实例");
}
public void setName(String name) {
System.out.println("第二步 使用set进行依赖注入");
this.name = name;
}
public void initMethod(){
System.out.println("第三步 执行初始化方法");
}
public void destoryMethod(){
System.out.println("第五步 执行销毁方法");
}
}
<bean id="person" class="com.pojo.Person" scope="singleton"
init-method="initMethod" destroy-method="destoryMethod">
<property name="name" value="小王"/>
</bean>