您的位置:首页 > 编程语言 > Java开发

Spring初探----Bean的生命周期

2016-04-16 13:32 399 查看

Bean的生命周期

  我们研究一个东西的生命周期,就是为了更好的掌握它,从而更好的使用它。Spring中的bean也当如此。

  我们知道,Spring中获取bean的两种方式:一是通过AppcationContext应用上下文接口获取,二是通过BeanFactory接口获取。二者不同之处在于前者在Spring容器启动加载xml文件时就会在内存当中实例化一个bean对象,后者只是在用户调用getbean()方法时才会在内存中实例化一个bean对象。后者的延迟加载bean对象,可以帮助节约内存,但是运行时负担会变重,因此BeanFactory方式主要用于移动端。

  我们说Bean的生命周期,其实就是指的是bean对象的生命周期(只是在spring容器框架内讨论,不涉及底层对象的一些例如JVM的类加载或者GC等底层内容)。

一 ApplicationContext方式获取的bean对象的生命周期

①bean对象的实例化

  这主要指的是启动spring容器加载xml文件时,spring会将我们的bean使用默认的无参的构造方法在内存中实例化,即这一步的“new”使用的是默认的无参构造方法,如果我们将默认的无参构造方法重写,那么会使用我们重写之后的方法;如果bean中没有无参构造方法的同时,却存在一个有参的构造方法,那么当spring在执行这一步时会报错。

  总结来说就是,bean中必须存在一个重写的无参的构造方法(当然可以同时存在其他的构造方法),或者bean中不存在构造方法(现在spring会依赖于个默认的无参构造方法)。但是也有例外,那就是在自动装配的时候,可以指定一个带参的构造方法而不会导致报错。后面写自动装配的时候我会再补充。

②set方法设置属性的值

  实例化之后,spring会去调用我们定义的bean 内部属性的有关set方法将我们在xml文件中配置的属性值加入到对象当中。值得注意的是,必须用默认的set()方法,名字不能随便改动。不然spring容器因会找不到set()方法而报错。

③如果bean实现了BeanNameAware接口,那么执行BeanNameAware接口的void setBeanName(String arg0)方法

  set()方法设置属性完成之后,如果我们定义的bean实现了BeanNameAware接口,那么spring容器会继续执行该接口的void setBeanName(String arg0)方法,从该方法我们可以得到bean的名字arg0的具体值。

④  如果bean实现了BeanFactoryAware接口,那么执行BeanFactoryAware的void setBeanFactory(BeanFactory arg0)方法

  完成③之后,满足④那么就能得到有关BeanFactory的有关信息。

⑤如果bean实现了ApplicationContextAware接口,那么执行 void setApplicationContext(ApplicationContext arg0)方法

  这一步可以得到应用上下文的有关信息arg0;

⑥如果另外存在一个类(或者叫bean)实现了BeanPostProcessor接口(该bean必须在xml文件中做配置),那么开始执行该接口的Object postProcessBeforeInitialization(Object arg0, String arg1)方法

  这个接口能够体现一点AOP(面向切面编程)的思想,它相当于一个过滤器,又叫后置处理器。这个接口有2个方法,分别为Object postProcessBeforeInitialization(Object arg0, String arg1)和Object postProcessAfterInitialization(Object arg0, String arg1)方法,满足⑥的条件之后经过上述5步的对象都将先执行Object postProcessBeforeInitialization(Object
arg0, String arg1)方法。而在剩下的Object postProcessAfterInitialization(Object arg0, String arg1)方法执行之前会存在一些其他的操作。

⑦如果bean实现了Initializing接口,那么执行它的void afterPropertiesSet()方法

⑧如果在xml文件中指定了bean的默认初始化方法,那么执行该方法。

⑨如果在第⑥步执行了Before方法,这一步执行剩下的After方法。

⑩使用bean对象。

⑪容器关闭时,如果bean类实现了disposable接口,那么执行该接口的方法。

⑫如果xml文件中配置了destroy方法,那么执行配置的destroy方法。

****************************分割线********************************

   如上,上述12步是针对于创建一个bean对象而言,如果是ApplicationContext方式加载bean,前面说过,会默认创建一个bean对象,也就是说,只要执行ApplicationContext ac = new ClassPathXmlApplicationContext("com/beanlife/beanlife.xml");(前面的xml文件路径是假定的),默认创建的那个对象就会经历上述过程。

  还有需要注意的一点就是,在任何时候,Object postProcessBeforeInitialization(Object arg0, String arg1)方法的返回值不能为null,否则会有空指针异常。当我们只是实例化一个bean并get他的时候,postProcessAfterInitialization(Object arg0, String arg1)方法的返回值可以为null。但是一旦我们要调用该bean对象的某个方法时,它的返回值就不能为null了,否则也会有空指针异常。

二 BeanFactory方式获取的bean对象的生命周期

与第一种ApplicationContext方式获取bean对象的方式相比,BeanFactory方式获取的对象不会经历ApplicationContextAware接口的处理,也不会执行过滤器BeanPostProcessor接口,但是应该注意到的是,BeanPostProcessor接口Before方法和After方法之间执行的Initializing接口方法和init-method会执行。

详细的周期如下:

①bean对象的实例化

  这主要指的是启动spring容器加载xml文件时,spring会将我们的bean使用默认的无参的构造方法在内存中实例化,即这一步的“new”使用的是默认的无参构造方法,如果我们将默认的无参构造方法重写,那么会使用我们重写之后的方法;如果bean中没有无参构造方法的同时,却存在一个有参的构造方法,那么当spring在执行这一步时会报错。

  总结来说就是,bean中必须存在一个重写的无参的构造方法(当然可以同时存在其他的构造方法),或者bean中不存在构造方法(现在spring会依赖于个默认的无参构造方法)

②set方法设置属性的值

  实例化之后,spring会去调用我们定义的bean 内部属性的有关set方法将我们在xml文件中配置的属性值加入到对象当中。值得注意的是,必须用默认的set()方法,名字不能随便改动。不然spring容器因会找不到set()方法而报错。

③如果bean实现了BeanNameAware接口,那么执行BeanNameAware接口的void setBeanName(String arg0)方法

  set()方法设置属性完成之后,如果我们定义的bean实现了BeanNameAware接口,那么spring容器会继续执行该接口的void setBeanName(String arg0)方法,从该方法我们可以得到bean的名字arg0的具体值。

④  如果bean实现了BeanFactoryAware接口,那么执行BeanFactoryAware的void setBeanFactory(BeanFactory arg0)方法

  完成③之后,满足④那么就能得到有关BeanFactory的有关信息。

⑤如果bean实现了Initializing接口,那么执行它的void afterPropertiesSet()方法

⑥如果在xml文件中指定了bean的默认初始化方法,那么执行该方法。

⑦使用bean对象。

⑧容器关闭时,如果bean类实现了disposable接口,那么执行该接口的方法。

⑨如果xml文件中配置了destroy方法,那么执行配置的destroy方法。

*********************分割线*************************

   前面我们也提到过,只有在getbean的时候,BeanFactory方式才会实例化一个bean对象,因此只是执行BeanFactory ac = new  XmlBeanFactory(new ClassPathResource("com/beanlife/beanlife.xml"));语句是无法进行上述过程的。只有通过ac再ac.getbean("name")时,上述过程才会经历。

   以上只是阶段总结,可能有不当之处,敬请指正。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring java bean