Spring Bean的生命周期
spring容器可以管理singleton作用域的bean的生命周期,可以调用创建、初始化、销毁等生命周期的方法。
对于prototype作用域的bean,spring容器只负责创建,创建后bean的实例就交给客户端代码来管理,spring容器不再跟踪其生命周期。
bean的生命周期
1、根据配置情况,调用bean的构造方法或工厂方法实例化bean
2、利用依赖注入完成bean中所有属性值的配置注入
3、如果bean实现了beannameaware接口,则调用setbeanname()方法传入当前bean的id。
4、如果bean实现了beanfactoryaware接口,则调用setbeanfactory()传入当前工厂实例的引用
5、如果bean实现了applicationcontextaware接口,则调用setapplicationcontext()方法传入当前applicationcontext实例的引用
6、如果beanpostprocessor和bean关联,则调用预初始化方法postprocessbeforeinitialzation()进行加工操作,spring aop即利用此实现。
7、如果bean实现了initializingbean接口,则调用afterpropertiesset()方法
8、如果在配置文件中通过init-method属性指定了初始化方法,则调用初始化方法
9、如果beanpostprocessor和bean关联,则调用初始化方法postprocessafterinitialization()。此时,bean已经可以被正常使用了。
10、如果指定了作用域为singleton,则将实例放在spring ioc的缓存池中,并触发spring容器对该bean的生命周期管理,如果指定作用域为prototype,则将该bean交给调用者,由调用者管理该bean的生命周期。
11、如果bean实现了disposablebean接口,则调用destory()方法销毁实例;
12、如果在配置文件中通过destory-method指定了bean的销毁方法,则调用该方法销毁实例。
说明:
以上接口中,均只有一个方法。
并不建议让bean实现多个接口,因为继承多个接口会使代码耦合较高。
注入依赖后的行为
spring提供2种方式,在bean全部属性设置完成后执行特定的行为:
- 实现initializingbean接口,在afterpropertiesset()方法中写代码。initializingbean接口中只有这一个方法。
- 在xml中使用init-method属性指定要调用的方法
可以同时使用这2种方式,会先执行afterpropertiesset(),再执行init-method属性指定的方法。
bean销毁之前的行为
spring提供了2种方式,在bean销毁之前执行特定的行为:
- 实现disposablebean接口,该接口只有destory()方法
- 在xml中用destory-method属性指定要调用的方法
可以同时使用这2种方式,会先执行destory(),再执行destory-method属性指定的方法。
说明:同时使用时,都是先执行接口中的方法,再执行xml中指定的方法。
示例
1 class student { 2 private string name; 3 4 public student(string name){ 5 this.name=name; 6 } 7 8 public string getname(){ 9 return name; 10 } 11 } 12 13 class teacher implements initializingbean, disposablebean { 14 @autowired 15 private student student; 16 17 public void say(){ 18 system.out.println(student.getname()+",叫家长来一下"); 19 } 20 21 public void xmlinit(){ 22 system.out.println("正在执行xml中init-method属性指定的初始化方法"); 23 } 24 25 @override 26 public void afterpropertiesset() throws exception { 27 system.out.println("正在执行initializingbean接口中的afterpropertiesset()方法"); 28 } 29 30 public void xmldestory(){ 31 system.out.println("正在执行xml中destory-method属性指定的方法"); 32 } 33 34 @override 35 public void destroy() throws exception { 36 system.out.println("正在执行disposablebean接口中的destory()方法"); 37 } 38 } 39 40 public class test { 41 public static void main(string[] args) { 42 abstractapplicationcontext applicationcontext=new classpathxmlapplicationcontext("applicationcontext.xml"); 43 teacher teacher=applicationcontext.getbean("teacher",teacher.class); 44 teacher.say(); 45 applicationcontext.registershutdownhook(); 46 } 47 48 }
在基于web的spring容器中,系统已经提供了相应的代码,在web应用关闭时,会自动关闭spring容器。
在非web的spring的容器中,需要手动调用abstractapplicationcontext类的registershutdownhook()方法向jvm注册一个关闭钩子,执行完前面的代码,会自动关闭spring容器。
applicatiocontext即spring容器。
applicationcontext是接口,没有实现registershutdownhook()方法,abstractapplicationcontext是applicationcontext的子类,实现了该方法,此处要声明为abstractapplicationcontext,不能声明为applicationcontext。
xml中的配置:
<context:annotation-config /> <bean id="student" class="my_package.student"> <constructor-arg value="张三" /> </bean> <bean id="teacher" class="my_package.teacher" init-method="xmlinit" destroy-method="xmldestory" />
运行程序,控制台输出如下:
正在执行initializingbean接口中的afterpropertiesset()方法 正在执行xml中init-method属性指定的初始化方法 张三,叫家长来一下 正在执行disposablebean接口中的destory()方法 正在执行xml中destory-method属性指定的方法