Spring Bean的生命周期
尽管还有一些在 Bean 实例化和销毁之间发生的活动,但是本章将只讨论两个重要的生命周期回调方法,它们在 bean 的初始化和销毁的时候是必需的。
为了定义安装和拆卸一个 bean,我们只要声明带有 init-method 和/或 destroy-method 参数的 。init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。
Bean的生命周期可以表达为:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁
package com.qyx.Bean; public class HelloWorld { private String message; public void setMessage(String message){ this.message = message; } public void getMessage(){ System.out.println("Your Message : " + message); } public void init(){ System.out.println("Bean is going through init."); } public void destroy(){ System.out.println("Bean will destroy now."); } }
<bean id="helloWorld" class="com.qyx.Bean.HelloWorld" init-method="init" destroy-method="destroy"> <property name="message" value="hello world"></property> </bean>
package com.qyx; import com.qyx.Bean.HelloWorld; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test02 { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld =context.getBean("helloWorld",HelloWorld.class); helloWorld.getMessage(); //registerShutdownHook()保证容器正常关闭,并且调用相关的destroy方法 ((ClassPathXmlApplicationContext) context).registerShutdownHook(); } }
如果你有太多具有相同名称的初始化或者销毁方法的 Bean,那么你不需要在每一个 bean 上声明初始化方法和销毁方法。框架使用 元素中的 default-init-method 和 default-destroy-method 属性提供了灵活地配置这种情况,如下所示:
<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-3.0.xsd" default-init-method="init" default-destroy-method="destroy"> <bean id="..." class="..."> <!-- collaborators and configuration for this bean go here --> </bean>
Spring——Bean 后置处理器
BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等。你也可以在 Spring 容器通过插入一个或多个 BeanPostProcessor 的实现来完成实例化,配置和初始化一个bean之后实现一些自定义逻辑回调方法。
你可以配置多个 BeanPostProcessor 接口,通过设置 BeanPostProcessor 实现的 Ordered 接口提供的 order 属性来控制这些 BeanPostProcessor 接口的执行顺序。
BeanPostProcessor 可以对 bean(或对象)实例进行操作,这意味着 Spring IoC 容器实例化一个 bean 实例,然后 BeanPostProcessor 接口进行它们的工作。
ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,注册这些 bean 为后置处理器,然后通过在容器中创建 bean,在适当的时候调用它。
package com.qyx.Bean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class InitHelloWorld implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("BeforeInitialization"+beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("AfterInitialization"+beanName); return bean; } }
<bean id="helloWorld" class="com.qyx.Bean.HelloWorld" init-method="init" destroy-method="destroy"> <property name="message" value="hello world"></property> </bean> <bean class="com.qyx.Bean.InitHelloWorld"></bean> </beans>
package com.qyx; import com.qyx.Bean.HelloWorld; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test02 { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld =context.getBean("helloWorld",HelloWorld.class); helloWorld.getMessage(); //registerShutdownHook()保证容器正常关闭,并且调用相关的destroy方法 ((ClassPathXmlApplicationContext) context).registerShutdownHook(); } }
Bean 定义继承
bean 定义可以包含很多的配置信息,包括构造函数的参数,属性值,容器的具体信息例如初始化方法,静态工厂方法名,等等。
子 bean 的定义继承父定义的配置数据。子定义可以根据需要重写一些值,或者添加其他值。
Spring Bean 定义的继承与 Java 类的继承无关,但是继承的概念是一样的。你可以定义一个父 bean 的定义作为模板和其他子 bean 就可以从父 bean 中继承所需的配置。
当你使用基于 XML 的配置元数据时,通过使用父属性,指定父 bean 作为该属性的值来表明子 bean 的定义。
<?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="beanTeamplate" class="com.qyx.Bean.HelloWorld"> <property name="message1" value="Hello World!"/> <property name="message2" value="Hello Second World!"/> </bean> <bean id="helloIndia" class="com.qyx.Bean.HelloIndia" parent="beanTeamplate"> <property name="message1" value="Hello India!"/> <property name="message3" value="Namaste India!"/> </bean> </beans>
package com.qyx.Bean; public class HelloIndia { private String message1; private String message2; private String message3; public void setMessage1(String message){ this.message1 = message; } public void setMessage2(String message){ this.message2 = message; } public void setMessage3(String message){ this.message3 = message; } public void getMessage1(){ System.out.println("India Message1 : " + message1); } public void getMessage2(){ System.out.println("India Message2 : " + message2); } public void getMessage3(){ System.out.println("India Message3 : " + message3); } }
package com.qyx.Bean; public class HelloWorld { private String message1; private String message2; public void setMessage1(String message){ this.message1 = message; } public void setMessage2(String message){ this.message2 = message; } public void getMessage1(){ System.out.println("World Message1 : " + message1); } public void getMessage2(){ System.out.println("World Message2 : " + message2); } }
package com.qyx; import com.qyx.Bean.HelloIndia; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test02 { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); HelloIndia helloWorld =context.getBean("helloIndia", HelloIndia.class); helloWorld.getMessage1(); helloWorld.getMessage2(); helloWorld.getMessage3(); //registerShutdownHook()保证容器正常关闭,并且调用相关的destroy方法 ((ClassPathXmlApplicationContext) context).registerShutdownHook(); } }