1、作用域
a、验证默认单例 equals 或者等于
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.xsd">
<!--
scope:设置bean的作用域
scope="singleton|prototype"
singleton(单例):表示获取该bean所对应的对象都是同一个
prototype(多例):表示获取该bean所对应的对象都不是同一个
-->
<bean id="student" class="com.lucky.spring.pojo.Student">
<property name="sid" value="1001"></property>
<property name="sname" value="张三"></property>
</bean>
</beans>
从IOC容器获取两个对象student1和student2,比较两个对象,输出为true。
@Test
public void testScope(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-scope.xml");
Student student1 = ioc.getBean(Student.class);
Student student2 = ioc.getBean(Student.class);
System.out.println(student1 == student2);
}
说明Spring中bean的作用域默认为单例。
equals默认比较的是内存地址,但在一些特殊情况下并不是,比如String类型,equals
比较的是两个字符串的内容,因为字符串是常量,每次创建一个新的字符串,先去常量池里面找一下,找到了就直接用,没有找到,才去新创建。
我们也可以通过scope标签,设置bean的作用域:
取值 | 含义 | 创建对象的时机 |
---|---|---|
singleton(默认) | 在IOC容器中,这个bean的对象始终为单实例 | 始化时 |
prototype | 这个bean在IOC容器中有多个实例 | 获取bean时 |
2、生命周期
新建User
package com.lucky.spring.pojo;
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
public User() {
System.out.println("生命周期1:实例化");
}
public User(Integer id, String username, String password, Integer age) {
this.id = id;
this.username = username;
this.password = password;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
System.out.println("生命周期2:依赖注入");
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
public void initMethod(){
System.out.println("生命周期3:初始化");
}
public void destroyMethod(){
System.out.println("生命周期4:销毁");
}
}
在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.xsd">
<bean id="user" class="com.lucky.spring.pojo.User" init-method="initMethod" destroy-method="destroyMethod">
<property name="id" value="1"></property>
<property name="username" value="admin"></property>
<property name="password" value="123456"></property>
<property name="age" value="23"></property>
</bean>
<bean id="myBeanPostProcessor" class="com.lucky.spring.process.MyBeanPostProcessor"></bean>
</beans>
测试bean声明周期
public class LifeCycleTest {
/**
* 1、实例化
* 2、依赖注入
* 3、后置处理器的postProcessBeforeInitialization
* 4、初始化,需要通过bean的init-method属性指定初始化的方法
* 5、后置处理器的postProcessAfterInitialization
* 6、IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法
*
* bean的后置处理器会在生命周期的初始化前后添加额外的操作
* 需要实现BeanPostProcessor接口且配置到IOC容器中
* 需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行
*
* 注意:
* 若bean的作用域为单例时,生命周期的前三个步骤会在获取IOC容器时执行
* 若bean的作用域为多例时,生命周期的前三个步骤会在获取bean时执行
*/
@Test
public void test(){
//ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
User user = ioc.getBean(User.class);
System.out.println(user);
ioc.close();
}
}
结论:spring中bean的声明周期为:
- bean对象创建(调用无参构造器)
- 给bean对象设置属性
- bean对象初始化之前操作(由bean的后置处理器负责)
- bean对象初始化(需在配置bean时指定初始化方法)
- bean对象初始化之后操作(由bean的后置处理器负责)
- bean对象就绪可以使用
- bean对象销毁(需在配置bean时指定销毁方法)
- IOC容器关闭