Spring 管理bean的生命周期

两个生命周期时间与bean关系尤为重要:
postinitialization(初始化后)和predestruction(销毁前)。

(Spring并不管理那些被配置成非单例bean的生命周期)



指定初始化方法:
  1. packagecn.partner4java.init;
  2. /**
  3. * 指定初始化方法
  4. * @author partner4java
  5. *
  6. */
  7. publicclassSimpleBean {
  8. privateString name;
  9. privateintage =0;
  10. publicvoidinit(){
  11. if(name ==null){
  12. System.out.println("name为空");
  13. }
  14. if(age ==0){
  15. System.out.println("age为0");
  16. }
  17. }
  18. publicString getName() {
  19. returnname;
  20. }
  21. publicvoidsetName(String name) {
  22. this.name = name;
  23. }
  24. publicintgetAge() {
  25. returnage;
  26. }
  27. publicvoidsetAge(intage) {
  28. this.age = age;
  29. }
  30. }
  1. <?xml version="1.0"encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="
  5. http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd">
  7. <bean id="simple1"class="cn.partner4java.init.SimpleBean"
  8. init-method="init">
  9. <property name="age"value="29"/>
  10. <property name="name"value="Dr. Jekyll"/>
  11. </bean>
  12. <bean id="simple2"class="cn.partner4java.init.SimpleBean"
  13. init-method="init">
  14. <property name="age"value="29"/>
  15. </bean>
  16. <bean id="simple3"class="cn.partner4java.init.SimpleBean"
  17. init-method="init">
  18. <property name="name"value="Mr. Hyde"/>
  19. </bean>
  20. </beans>

调用:
  1. //在调用获取的时候就会调用init,在调用init之前,已经使用控制反转设置方法依赖注入设置进数据
  2. BeanFactory beanFactory = getBeanFactory();
  3. System.out.println("simple1");
  4. beanFactory.getBean("simple1");
  5. System.out.println("simple2");
  6. beanFactory.getBean("simple2");
  7. System.out.println("simple3");
  8. beanFactory.getBean("simple3");
  9. //后台打印:
  10. //simple1
  11. //simple2
  12. //name为空
  13. //simple3
  14. //age为0




实现InitializingBean接口:
Spring中InitializingBean接口允许你在bean的代码中这样定义:你希望bean能接收到Spring已经完成对其配置的通知。就像使用初始化方法时一样,你可以借机检查bean的配置以确保其有效,若要必要,还可以给出默认值。
  1. publicclassSimpleBeanIBimplementsInitializingBean {
  2. privatestaticfinalString DEFAULT_NAME ="Jan Machacek";
  3. privateString name;
  4. privateintage =0;
  5. publicString getName() {
  6. returnname;
  7. }
  8. publicvoidsetName(String name) {
  9. this.name = name;
  10. }
  11. publicintgetAge() {
  12. returnage;
  13. }
  14. publicvoidsetAge(intage) {
  15. this.age = age;
  16. }
  17. @Override
  18. publicString toString() {
  19. finalStringBuilder sb =newStringBuilder();
  20. sb.append("SimpleBean");
  21. sb.append("{name='").append(name).append('\'');
  22. sb.append(", age=").append(age);
  23. sb.append('}');
  24. returnsb.toString();
  25. }
  26. publicvoidafterPropertiesSet()throwsException {
  27. System.out.println("initializing bean");
  28. if(this.name ==null) {
  29. System.out.println("No name specified, using default.");
  30. this.name = DEFAULT_NAME;
  31. }
  32. if(this.age ==0) {
  33. thrownewIllegalArgumentException("You must set the [age] property bean of type ["+ getClass().getName() +"]");
  34. }
  35. }
  36. }



决议顺序:
Spring首先调用InitializingBean.afterPropertiesSet()方法,然后再调用初始化方法。(建议如果存在顺序,都写入到afterPropertiesSet中调用。)


afterPropertiesSet方法和类的继承:
例子抽象父类实现了接口,但是把afterPropertiesSet定义成了final,不可被子类覆盖,也就是去实现一些通用的初始化,然后再调用了自己定义的initSimple()初始化方法。
父类:
  1. publicabstractclassSimpleBeanSupportimplementsInitializingBean {
  2. privateString value;
  3. /**
  4. * Subclasses may override this method to perform additional initialization.
  5. * This method gets invoked after the initialization of the {@link SimpleBeanSupport}
  6. * completes.
  7. * @throws Exception If the subclass initialization fails.
  8. */
  9. protectedvoidinitSimple()throwsException {
  10. // do nothing
  11. }
  12. publicfinalvoidafterPropertiesSet()throwsException {
  13. Assert.notNull(this.value,"The [value] property of ["+ getClass().getName() +"] must be set.");
  14. initSimple();
  15. }
  16. publicfinalvoidsetValue(String value) {
  17. this.value = value;
  18. }
  19. protectedfinalString getValue() {
  20. returnthis.value;
  21. }
  22. }

继承:
  1. publicclassSoutSimpleBeanextendsSimpleBeanSupport {
  2. privateString person;
  3. protectedvoidinitSimple()throwsException {
  4. Assert.notNull(this.person,"The [person] property of ["+ getClass().getName() +"] must be set.");
  5. }
  6. publicvoidsetPerson(String person) {
  7. this.person = person;
  8. }
  9. @Override
  10. publicString toString() {
  11. returnString.format("%s says \"%s\"",this.person, getValue());
  12. }
  13. }

配置文件:
  1. <?xml version="1.0"encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="
  5. http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd">
  7. <bean id="simple1"class="com.apress.prospring2.ch04.lifecycle.SoutSimpleBean">
  8. <property name="person"value="Winston Churchill"/>
  9. <property name="value"value="This report, by its very length, defends itself against the risk of being read."/>
  10. </bean>
  11. </beans>



嵌入bean的销毁:
1、bean销毁时执行某一方法
  1. publicclassDestructiveBeanimplementsInitializingBean {
  2. privateInputStream is =null;
  3. privateString filePath =null;
  4. publicvoidafterPropertiesSet()throwsException {
  5. System.out.println("Initializing Bean");
  6. Assert.notNull(this.filePath,"The [filePath] property of ["+ getClass().getName() +"] must be set.");
  7. newFile(this.filePath).createNewFile();
  8. this.is =newFileInputStream(this.filePath);
  9. }
  10. publicvoiddestroy() {
  11. System.out.println("Destroying Bean");
  12. if(this.is !=null) {
  13. try{
  14. this.is.close();
  15. this.is =null;
  16. newFile(this.filePath).delete();
  17. }catch(IOException ex) {
  18. System.err.println("WARN: An IOException occured"
  19. +" while trying to close the InputStream");
  20. }
  21. }
  22. }
  23. publicvoidsetFilePath(String filePath) {
  24. this.filePath = filePath;
  25. }
  26. @Override
  27. publicString toString() {
  28. finalStringBuilder sb =newStringBuilder();
  29. sb.append("DestructiveBean");
  30. sb.append("{is=").append(is);
  31. sb.append(", filePath='").append(filePath).append('\'');
  32. sb.append('}');
  33. returnsb.toString();
  34. }
  35. }

配置文件:
  1. <?xml version="1.0"encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="
  5. http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd">
  7. <bean id="destructive"class="com.apress.prospring2.ch04.lifecycle.DestructiveBean"
  8. destroy-method="destroy">
  9. <property name="filePath"value="/tmp/prospring25"/>
  10. </bean>
  11. </beans>

2、实现DisposableBean接口
DisposableBean接口提供了destory方法。
  1. publicclassDestructiveBeanIimplementsInitializingBean, DisposableBean {
  2. privateInputStream is =null;
  3. privateString filePath =null;
  4. publicvoidafterPropertiesSet()throwsException {
  5. System.out.println("Initializing Bean");
  6. Assert.notNull(this.filePath,"The [filePath] property of ["+ getClass().getName() +"] must be set.");
  7. newFile(this.filePath).createNewFile();
  8. this.is =newFileInputStream(this.filePath);
  9. }
  10. publicvoiddestroy() {
  11. System.out.println("Destroying Bean");
  12. if(this.is !=null) {
  13. try{
  14. this.is.close();
  15. this.is =null;
  16. newFile(this.filePath).delete();
  17. }catch(IOException ex) {
  18. System.err.println("WARN: An IOException occured"
  19. +" while trying to close the InputStream");
  20. }
  21. }
  22. }
  23. publicvoidsetFilePath(String filePath) {
  24. this.filePath = filePath;
  25. }
  26. @Override
  27. publicString toString() {
  28. finalStringBuilder sb =newStringBuilder();
  29. sb.append("DestructiveBean");
  30. sb.append("{is=").append(is);
  31. sb.append(", filePath='").append(filePath).append('\'');
  32. sb.append('}');
  33. returnsb.toString();
  34. }
  35. }

配置文件:
  1. <?xml version="1.0"encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="
  5. http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd">
  7. <bean id="destructive"class="com.apress.prospring2.ch04.lifecycle.DestructiveBeanI">
  8. <property name="filePath"value="/tmp/prospring25"/>
  9. </bean>
  10. </beans>

3、使用关闭钩子
注入关闭代码:
  1. publicclassShutdownHookimplementsRunnable {
  2. privateConfigurableListableBeanFactory beanFactory;
  3. publicShutdownHook(ConfigurableListableBeanFactory beanFactory) {
  4. Assert.notNull(beanFactory,"The 'beanFactory' argument must not be null.");
  5. this.beanFactory = beanFactory;
  6. }
  7. publicvoidrun() {
  8. this.beanFactory.destroySingletons();
  9. }
  10. }

调用代码:
  1. publicclassShutdownHookDemo {
  2. publicstaticvoidmain(String[] args)throwsIOException {
  3. XmlBeanFactory factory =newXmlBeanFactory(newClassPathResource("/META-INF/spring/lifecycledemo5-context.xml"));
  4. Runtime.getRuntime().addShutdownHook(newThread(newShutdownHook(factory)));
  5. newBufferedInputStream(System.in).read();
  6. }
  7. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值