理解 Spring bean 的生命周期很容易。当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。
在@Bean注解中有initMethod和destroyMethod两个属性,其中initMethod属性指定一个方法,在实例化 bean 完成后,立即调用该方法。destroyMethod指定一个方法,只有从容器中移除 bean 时,才能调用该方法。
Bean的生命周期可以表达为:Bean的定义——Bean的setter——Bean的初始化——Bean的使用——Bean的销毁 。
实例
接上一节案例实现。
1.改写Person实体类
package com.entity;
import javax.annotation.Resource;
public class Person {
private String name;
private String gender;
private int age;
//方式一:@Autowired+@Qualifier
//@Autowired
//@Qualifier("car2")
//方式二:@Resource(name="xxx") 或者属性名字和bean的name保持一致。
@Resource(name="car2")
//@Resource
private Car car;
public Person() {
System.out.println("Person Constructor...");
}
public Person(String name, String gender, int age) {
this();
this.name = name;
this.gender = gender;
this.age = age;
}
//bean的初始化方法
public void initPerson(){
System.out.println("initPerson()...");
}
//bean的销毁方法
public void destroyPerson(){
System.out.println("destroyPerson()...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
System.out.println("setCar(Car car)...");
this.car = car;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", car=" + car +
'}';
}
}
2.在SpringConfiguration配置bean.
在@Bean中使用initMethod和destroyMethod定义bean的初始化方法和销毁方法。
package com.config;
import com.entity.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
@ComponentScan(basePackages = "com")
public class SpringConfiguration {
@Bean(name = {"p1","person"},initMethod = "initPerson",destroyMethod = "destroyPerson")
@Scope("singleton" ) // 注意:作用域必须是singleton,否则bean的销毁方法不执行。
public Person getPerson(){
return new Person("zhangsan","男",20);
}
}
3.测试生命周期
package com.test;
import com.config.SpringConfiguration;
import com.entity.Person;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
Person person = (Person) context.getBean("p1");
System.out.println(person);
context.close();//关闭IOC容器
}
}
运行结果:
Person Constructor...
initPerson()...
Person{name='zhangsan', gender='男', age=20, car=Car{brand='BENZ', color='red'}}
destroyPerson()...
如果Person的bean不是在SpringConfiguration配置中初始化。我们需使用@Component和@PostConstruct以及@PreDestroy实现。代码如下:
package com.entity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
@Component("p1")
public class Person {
@Value("zhangsan")
private String name;
@Value("男")
private String gender;
@Value("20")
private int age;
//方式一:@Autowired+@Qualifier
//@Autowired
//@Qualifier("car2")
//方式二:@Resource(name="xxx") 或者属性名字和bean的name保持一致。
@Resource(name="car2")
//@Resource
private Car car;
public Person() {
System.out.println("Person Constructor...");
}
public Person(String name, String gender, int age) {
this();
this.name = name;
this.gender = gender;
this.age = age;
}
//bean的初始化方法
@PostConstruct
public void initPerson(){
System.out.println("initPerson()...");
}
//bean的销毁方法
@PreDestroy
public void destroyPerson(){
System.out.println("destroyPerson()...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
System.out.println("setCar(Car car)...");
this.car = car;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", car=" + car +
'}';
}
}
如果使用XML配置方式,init-method和destroy-method用法如下:
<bean class="com.entity.Person" name="p1,person" scope="prototype" init-method="initPerson" destroy-method="destroyPerson">
<property name="name" value="zhangsan"/>
<property name="gender" value="男"/>
<property name="age" value="20"/>
<property name="car" ref="car"/>
</bean>