spring心得3--bean的生命周期结合案例详细讲解@普通期图解与uml图解一并分析

本文深入解析Spring框架中Bean的生命周期,从容器初始化到销毁的每个阶段,并通过实际代码案例展示Bean工厂与应用上下文在创建、管理、维护Bean过程中的区别与联系。文章还特别强调了BeanPostProcessor在生命周期中的作用以及单例bean的加载机制。

1.继上一篇博客续将,bean生命周期理论概括

 bean被载入到容器中时,他的生命周期就开始了。bean工厂在一个bean可以使用前完成很多工作:

1).容器寻找bean的定义信息并实例化。

2).使用依赖注入,spring按bean定义信息配置bean的所有属性。

3).若bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递bean的ID。

4).若bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

5).若BeanPostProcessor和bean关联,则它们的 postProcessBeforeInitialization()方法被调用。

6).若bean指定了ini-method方法、,它将被调用。

7).最后,若有BeanPostProcessor和bean关联,则它们的postProcessAfterInitialization()方法被调用。

    将bean从工厂中删掉有两种方法:

1).若bean实现了DisposableBean接口,distroy()方法被调用。

2).如果指定了定制的销毁方法,就调用这个方法。

bean在应用上下文中的生命周期和在bean工厂的生命周期唯一不同的是:若bean实现了ApplicationContextAware()接口,setApplicationContext()方法会被调用。

2.案例加注释详细剖解bean的生命周期

  测试类的代码

package www.csdn.spring.test;

 

import org.junit.Test;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.BeanFactory;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;

import org.springframework.beans.factory.xml.XmlBeanFactory;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.core.io.ClassPathResource;

 

import www.csdn.spring.dao.impl.HelloDaoImpl;

 

publicclass CycleTest {

 

   @Test

   publicvoid cycleTest() {

      /**

       * bean的生命周期 bean被载入到容器中时,他的生命周期就开始了。bean工厂在一个bean可以使用前完成很多工作:

       * 

       * 1.容器寻找bean的定义信息并实例化。使用bean工厂或扩展的bean工厂context上下文来说明该知识点

       * ClassPathXmlApplicationContext context = new

       * ClassPathXmlApplicationContext("spring-dao.xml");

       * 

       * 2.使用依赖注入,spring按bean定义信息配置bean的所有属性。

       * 通过在dao中声明content属性并创建setter方法以及spring-dao.xml配置这样的信息来说明: <property

       * name="content" value="hello!杨凯!"/>

       * 

       * 3.若bean实现了BeanNameAware接口,工厂调用Bean的setBeanName ()方法传递bean的ID。

       * 通过dao中的继承改接口,并实现改接口的相应方法public void setBeanName(String

       * beanId)来说明知识点;重点代码在dao中

       * 

       * 4.若bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

       * 通过dao中的继承改接口,并实现改接口的相应方法public void setBeanFactory(BeanFactory

       * factory) throws BeansException 来说明该知识点,重点代码在dao中。

       * 

       * 5.若BeanPostProcessor和bean关联,则它们的

       * postProcessBeforeInitialization()方法被调用。

       * 改类是个全局控局类,只要在一个bean的配置文件和相应bean类中实现了该接口并重写了该接口的方法,在整个项目的bean类中都会起作用

       * 所以这里为了更好说明问题,新建一个BeanPostProcessorImpl类去实现BeanPostProcessor接口

       * 

       * 6.若bean指定了ini-method、destroy-method方法,它将被调用。

       * 通过在bean的指定spring配置文件中配置属性init-method="init" destroy-method="destroy"

       * 尤其是使destroy-method方法起作用的使用,一定要在测试类中关闭bean工厂对象context.close();

       * 

       * 7.最后,若有BeanPostProcessor和bean关联,则它们的postProcessAfterInitialization()

       * 方法被调用。、同第五个before一样

       */

 

      /*// 使用上下文context模拟的bean的生命周期:使用ClassPathXmlApplicationContext对象接收

       ClassPathXmlApplicationContext context = new

       ClassPathXmlApplicationContext("spring-dao.xml");

 

       context.getBean("helloDaoImpl",HelloDaoImpl.class).sayHello(); 

      // 执行关闭,以下两个方法都可以使destory-method的方法的执行

      context.destroy();

      // context.close();

      */

      

      //使用ApplicationContext对象接收,调用getBean与上面的方法一样,不同的是销毁与关闭的方法需要强转为AbstractApplicationContext类型的

      ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");

      context.getBean("helloDaoImpl",HelloDaoImpl.class).sayHello(); 

      // 执行关闭,以下两个方法都可以使destory-method的方法的执行

      //((AbstractApplicationContext) context).destroy();

       ((ConfigurableApplicationContext) context).close();

      

      

       System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=--=-=-=-=-=-==");

       

      /**

       * 除了应用上下文提供的附加功能外,应用上下文与bean工厂的另一个重要区别是关于单例bean 如何被加载。

       * bean工厂延迟加载所有bean,直到getBean() 方法被调用。应用上下文会在启动后预载入所有单例bean.

       * 这样可确保应用不需要等待他们被创建。

       *  使用bean工厂模拟的bean的生命周期:

       */

      ConfigurableBeanFactory cbf = new XmlBeanFactory(new ClassPathResource("spring-dao.xml"));

      

      /*bean工厂调用BeanPostProcessor类的方法也与上下文对象不一样,上下文对象直接在配置文件使用bean标签指明即可,

       * 而在bean工厂中需要下面一个方法去调用该类

       */

      //cbf.addBeanPostProcessor(new BeanPostProcessorImpl());

      //这种方法也可以调用BeanPostProcessor,与上面结果一样

      cbf.addBeanPostProcessor(cbf.getBean("beanPostProcessorImpl",BeanPostProcessorImpl.class));

      

      

      //只有使用getBean方法后所有的初始化信息才会执行

      cbf.getBean("helloDaoImpl",HelloDaoImpl.class);

      //使用下面的方法销毁所有的单例对象

      cbf.destroySingletons();

   }

}

spring配置文件的代码

<?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">

 

   <!-- spring容器就是负责创建、管理、维护Bean 并且能够依赖注入到相应组件上 -->

   <bean id="helloDaoImpl" class="www.csdn.spring.dao.impl.HelloDaoImpl"

      scope="singleton" lazy-init="false" init-method="init" destroy-method="destroy">

      <!-- 通过set方法注入 -->

      <property name="content" value="hello!杨凯!" />

   </bean>

 

   <!-- spring-service.xml引用的改配置文件,所以在前者中加入了lazy-init="false",这里可以不写也会起作用;

      lazy-init属性的意思是:是否延迟加载,就是一创建 spring容器就去实例化对应容器对象,即执行改对象的构造器,而不是在使用的时候才去加载

      lazy-init="false" ,默认的值为default,但是default=false -->

 

   <!-- BeanPostProcessor与当前的bean都进行关联 -->

   <bean id="beanPostProcessorImpl" class="www.csdn.spring.test.BeanPostProcessorImpl" />

</beans>

bean实例代码(这里把dao做bean讲解)

package www.csdn.spring.dao.impl;

 

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.BeanFactory;

import org.springframework.beans.factory.BeanFactoryAware;

import org.springframework.beans.factory.BeanNameAware;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

 

import www.csdn.spring.dao.HelloDao;

 

public class HelloDaoImpl implements HelloDao, BeanNameAware, BeanFactoryAware,

      ApplicationContextAware,InitializingBean {

 

   private String content;

 

   public void setContent(String content) {

      System.out.println("say:setter注入的内容是:" + content);

      this.content = content;

   }

 

   public HelloDaoImpl() {

      System.out.println("HelloDaoImpl实例化。。。。");

   }

 

   @Override

   public void sayHello() {

      System.out.println("say:hello world!");

   }

 

   public void init() {

      System.out.println("----init方法执行了----");

   }

 

   public void destroy() {

      System.out.println("=====destory方法执行了=====");

   }

 

   @Override

   public void setBeanName(String beanId) {

      /*

       * 这里只能查看beanId,即使修改也只在改方法内生效,并没有传出去,所以在其他方法中使用的beanId还是配置文件中传过来的id

       * 而不是被修改过的id;并且这里只能查看id,不能使用bean工厂操作,也就是说不能使用传过来的id去调用bean工厂来操作类

       * 更不能使用修改后的id去调用bean工厂来操作类

       */

      System.out.println("传递bean的ID为:"+beanId);

 

      beanId = "hello";

       System.out.println("修改后的bean的ID为:"+beanId);

   }

 

   @Override

   public void setBeanFactory(BeanFactory factory) throws BeansException {

      /*

       * 这里可以使用bean工厂执行bean类中的方法的前提是在配置中使用scope="singleton"

       * lazy-init="default" 这两个属性才可以达到预期效果,否则控制台根本不输出内容

       */

      System.out.println(factory.getClass()+"-----"+factory.getBean("helloDaoImpl"));

       factory.getBean("helloDaoImpl",HelloDaoImpl.class).sayHello();

   }

 

   @Override

   public void setApplicationContext(ApplicationContext applicationContext)

         throws BeansException {

      System.out.println("--调用:" + applicationContext);

   }

 

   @Override

   public void afterPropertiesSet() throws Exception {

      System.out.println("----initializingBean接口的方法被调用了。。。。");

   }

 

}


 

3.bean的生命周期状态图解

     第一个图中是使用上下文对象通过spring配置文件来创建、管理、维护的状态图解,蓝色字体是对比第二张图的不同之处;第二张图是bean工厂对象过spring配置文件来创建、管理、维护的状态图解。

4.bean生命周期的UML状态图解

     上下文对象

    Bean工厂对象

 

      注:bean在ApplicationContext中的生命周期与BeanFactory中唯一的不同是若实现了ApplicationContextAware()接口则会调用setApplicationContext()方法,执行顺序是在setBeanFactory()方法之后,预初始化方法之前。

转载于:https://www.cnblogs.com/yangkai-cn/archive/2013/04/24/4016893.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值