Spring容器可以管理bean的生命周期。SpringIOC容器对bean的生命周期进行管理的过程:
- 通过构造器或工厂方法创建bean实例
- 为bean的属性赋值或设置bean的引用
- 调用bean的初始化方法(init-method)
- bean初始化完成——此时bean可以使用了
- 当容器关闭时,调用bean的销毁方法(destroy-method)
在配置文件中,可以在bean的声明里设置init-method和destroy-method属性,来为bean指定初始化方法和销毁方法。具体实现如下:
实体类:增加初始化方法和销毁方法
package entity; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.Date; import java.util.List; import java.util.Map; public class Student extends Person{ private Integer id; private String name; private String gender; private String liveCountry; private Date createTime; private Teacher teacher; private List
subjects; private Map scoreMap; public Student(){ System.out.println("student无参构造"); } public Student(Integer id, String name) { System.out.println("student含id、name的构造函数"); this.id = id; this.name = name; } public Student(Integer id, String name, String gender, String liveCountry) { System.out.println("student含id、name、gender、liveCountry的构造函数"); this.id = id; this.name = name; this.gender = gender; this.liveCountry = liveCountry; } /** * 初始化方法 */ public void initStudent(){ System.out.println("init......"); this.id = 2; this.name = "rose"; } /** * 销毁方法 */ public void destroyStudent(){ System.out.println("destroy......"); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } 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 String getLiveCountry() { return liveCountry; } public void setLiveCountry(String liveCountry) { this.liveCountry = liveCountry; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } public List getSubjects() { return subjects; } public void setSubjects(List subjects) { this.subjects = subjects; } public Map getScoreMap() { return scoreMap; } public void setScoreMap(Map scoreMap) { this.scoreMap = scoreMap; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", gender='" + gender + '\'' + ", liveCountry='" + liveCountry + '\'' + ", createTime=" + createTime + ", teacher=" + teacher + ", subjects=" + subjects + ", scoreMap=" + scoreMap + '}'; } } 配置文件:指定引用的初始化方法和销毁方法
测试类:
package controller; import entity.Student; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args){ // 读取配置文件 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-bean.xml"); Student student1 = (Student)ctx.getBean("student1"); System.out.println(student1); // 关闭spring容器 ctx.close(); } }
运行结果:
如果使用注解方式来配置bean,可以结合使用@PostConstruct和@PreDestroy来代替配置文件中的相关配置。具体实现如下:
配置文件:配置扫描注解
实体类代码:
package entity; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.Date; import java.util.List; import java.util.Map; @Repository @Lazy(value = true) @Scope("singleton") public class Student extends Person{ private Integer id; private String name; private String gender; private String liveCountry; private Date createTime; private Teacher teacher; private List
subjects; private Map scoreMap; public Student(){ System.out.println("student无参构造"); } public Student(Integer id, String name) { System.out.println("student含id、name的构造函数"); this.id = id; this.name = name; } public Student(Integer id, String name, String gender, String liveCountry) { System.out.println("student含id、name、gender、liveCountry的构造函数"); this.id = id; this.name = name; this.gender = gender; this.liveCountry = liveCountry; } /** * 初始化方法 */ @PostConstruct public void initStudent(){ System.out.println("init......"); this.id = 2; this.name = "rose"; } /** * 销毁方法 */ @PreDestroy public void destroyStudent(){ System.out.println("destroy......"); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } 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 String getLiveCountry() { return liveCountry; } public void setLiveCountry(String liveCountry) { this.liveCountry = liveCountry; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } public List getSubjects() { return subjects; } public void setSubjects(List subjects) { this.subjects = subjects; } public Map getScoreMap() { return scoreMap; } public void setScoreMap(Map scoreMap) { this.scoreMap = scoreMap; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", gender='" + gender + '\'' + ", liveCountry='" + liveCountry + '\'' + ", createTime=" + createTime + ", teacher=" + teacher + ", subjects=" + subjects + ", scoreMap=" + scoreMap + '}'; } } 执行测试类,得到相同的结果。
注意:必须确保scope为singleton,否则@PreDestroy修饰的方法不会执行
bean的后置处理器:实际上还可以定制更细粒度的bean生命周期方法,Spring提供了bean的后置处理器,可以在bean的初始化方法前后,对bean进行额外的处理。bean后置处理器是对Spring容器中的所有bean实例进行相同处理,而不是单一的、针对性的。其典型应用是:检查bean属性的正确性或根据特定标准更改bean属性。
bean后置处理器需要实现【org.springframework.beans.factory.config.BeanPostProcessor】接口,重写其中的postProcessBeforeInitialization、postProcessAfterInitialization方法,在初始化方法调用前后,Spring容器会把bean实例通过这两个方法进行处理。加入后置处理器的bean生命周期为:
- 通过构造器或工厂方法创建bean实例
- 为bean的属性赋值或设置bean的引用
- 后置处理器的postProcessBeforeInitialization方法
- 调用bean的初始化方法(init-method)
- 后置处理器的postProcessAfterInitialization方法
- bean初始化完成——此时bean可以使用了
- 当容器关闭时,调用bean的销毁方法(destroy-method)
具体实现如下:
创建后置处理器:
package entity; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class BeanProcessor implements BeanPostProcessor { //init-method之前被调用 @Override public Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException{ System.out.println("postProcessBeforeInitialization...bean:"+var1.toString()+"beanName:"+var2); return var1; } //init-method之后被调用 @Override public Object postProcessAfterInitialization(Object var1, String var2) throws BeansException{ System.out.println("postProcessAfterInitialization...bean:"+var1.toString()+"beanName:"+var2); return var1; } }
配置文件中配置后置处理器:
测试类:
package controller; import entity.Student; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args){ // 读取配置文件 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-bean.xml"); Student student1 = (Student)ctx.getBean("student1"); System.out.println(student1); // 关闭spring容器 ctx.close(); } }
运行结果: