码迷,mamicode.com
首页 > 编程语言 > 详细

Spring Bean的生命周期

时间:2019-11-08 12:49:47      阅读:79      评论:0      收藏:0      [点我收藏+]

标签:init   初始   proc   frame   destory   div   上下文   initial   sso   

原文地址:http://www.cnblogs.com/zrtqsk/p/3735273.html

Spring作为当前Java最流行、最强大的轻量级框架,受到了程序员的热烈欢迎。准确的了解Spring Bean的生命周期是非常必要的。我们通常使用ApplicationContext作为Spring容器。这里,我们讲的也是 ApplicationContext中Bean的生命周期。而实际上BeanFactory也是差不多的,只不过处理器需要手动注册。

1、生命周期流程图

技术图片

技术图片

若容器注册了以上各种接口,程序那么将会按照以上的流程进行。下面将仔细讲解各接口作用。

2、各种接口方法分类

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

(1)Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法;

(2)Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法;

(3)容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”;

(4)工厂后处理器接口方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

3、演示

我们用一个简单的Spring Bean来演示一下Spring Bean的生命周期。

(1)首先是一个简单的Spring Bean,调用Bean自身的方法和Bean级生命周期接口方法。为了方便演示,它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,同时有两个方法,对应配置文件中<bean>的init-method和destroy-method。如下:

技术图片
  1 package com.ly.demo.spring.bean;
  2 
  3 import org.springframework.beans.BeansException;
  4 import org.springframework.beans.factory.*;
  5 
  6 public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
  7     private String name;
  8     private String address;
  9     private String phone;
 10 
 11     private BeanFactory beanFactory;
 12     private String beanName;
 13 
 14     public Person() {
 15         System.out.println("【构造器】调用Person的构造器实例化");
 16     }
 17 
 18     public String getName() {
 19         return name;
 20     }
 21 
 22     public void setName(String name) {
 23         System.out.println("【注入属性】注入属性name");
 24         this.name = name;
 25     }
 26 
 27     public String getAddress() {
 28         return address;
 29     }
 30 
 31     public void setAddress(String address) {
 32         System.out.println("【注入属性】注入属性address");
 33         this.address = address;
 34     }
 35 
 36     public String getPhone() {
 37         return phone;
 38     }
 39 
 40     public void setPhone(String phone) {
 41         System.out.println("【注入属性】注入属性phone");
 42         this.phone = phone;
 43     }
 44 
 45     @Override
 46     public String toString() {
 47         return "Person{" +
 48                 "name=‘" + name + ‘\‘‘ +
 49                 ", address=‘" + address + ‘\‘‘ +
 50                 ", phone=‘" + phone +
 51                 ‘}‘;
 52     }
 53 
 54     /**
 55      * 这是BeanFactoryAware接口方法
 56      */
 57     @Override
 58     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
 59         System.out.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
 60         this.beanFactory = beanFactory;
 61     }
 62 
 63     /**
 64      * 这是BeanNameAware接口方法
 65      */
 66     @Override
 67     public void setBeanName(String s) {
 68         System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
 69         this.beanName = s;
 70     }
 71 
 72     /**
 73      * 这是DisposableBean接口方法
 74      */
 75     @Override
 76     public void destroy() throws Exception {
 77         System.out.println("【DisposableBean接口】调用DisposableBean.destroy()");
 78     }
 79 
 80     /**
 81      * 这是InitializingBean接口方法
 82      */
 83     @Override
 84     public void afterPropertiesSet() throws Exception {
 85         System.out.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
 86     }
 87 
 88     /**
 89      * 通过<bean></bean>的init-method属性指定的初始化方法
 90      */
 91     public void myInit() {
 92         System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
 93     }
 94 
 95     /**
 96      * 通过<bean></bean>的destroy-method属性指定的初始化方法
 97      */
 98     public void myDestroy() {
 99         System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的销毁方法");
100     }
101 }
View Code

 

(2)接下来是演示BeanPostProcessor接口的方法,如下:

技术图片
 1 package com.ly.demo.spring.bean;
 2 
 3 import org.springframework.beans.BeansException;
 4 import org.springframework.beans.factory.config.BeanPostProcessor;
 5 
 6 public class MyBeanPostProcessor implements BeanPostProcessor {
 7 
 8     public MyBeanPostProcessor() {
 9         super();
10         System.out.println("这是BeanPostProcessor实现类构造器!!!");
11     }
12 
13     @Override
14     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
15         System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");
16         return bean;
17     }
18 
19     @Override
20     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
21         System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");
22         return bean;
23     }
24 }
View Code

 

如上,BeanPostProcessor接口包括2个方法postProcessBeforeInitialization和postProcessAfterInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name,返回值也都是要处理的Bean对象。

(3)InstantiationAwareBeanPostProcessor接口本质是BeanPostProcessor的子接口,一般我们继承Spring为其提供的适配器类InstantiationAwareBeanPostProcessorAdapter来使用它,如下:

技术图片
 1 package com.ly.demo.spring.bean;
 2 
 3 import org.springframework.beans.BeansException;
 4 import org.springframework.beans.PropertyValues;
 5 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
 6 
 7 import java.beans.PropertyDescriptor;
 8 
 9 public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
10 
11     public MyInstantiationAwareBeanPostProcessor() {
12         super();
13         System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!!");
14     }
15 
16     /**
17      * 接口方法、实例化Bean之前调用
18      */
19     @Override
20     public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
21         System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");
22         return null;
23     }
24 
25     /**
26      * 接口方法、设置某个属性时调用
27      */
28     @Override
29     public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
30         System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");
31         return pvs;
32     }
33 
34     /**
35      * 接口方法、实例化Bean之后调用
36      */
37     @Override
38     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
39         System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");
40         return null;
41     }
42 }
View Code

 

这个类包括3个方法,其中postProcessAfterInitialization就是重写了BeanPostProcessor的方法,postProcessPropertyValues方法用来操作属性,返回值也应该是PropertyValues对象。

(4)演示工厂后处理器接口方法,如下:

技术图片
 1 package com.ly.demo.spring.bean;
 2 
 3 import org.springframework.beans.BeansException;
 4 import org.springframework.beans.factory.config.BeanDefinition;
 5 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
 6 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 7 
 8 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
 9 
10     public MyBeanFactoryPostProcessor() {
11         super();
12         System.out.println("这是BeanFactoryPostProcessor实现类构造器!!!");
13     }
14 
15     @Override
16     public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
17         System.out.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
18         BeanDefinition definition = configurableListableBeanFactory.getBeanDefinition("person");
19         definition.getPropertyValues().addPropertyValue("phone", "13156788899");
20     }
21 }
View Code

 

(5)配置文件beans.xml如下,使用ApplicationContext,处理器不用手动注册:

技术图片
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <beans xmlns="http://www.springframework.org/schema/beans"
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
 5     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
 6     xsi:schemaLocation="
 7             http://www.springframework.org/schema/beans 
 8             http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
 9 
10     <bean id="beanPostProcessor" class="springBeanTest.MyBeanPostProcessor">
11     </bean>
12 
13     <bean id="instantiationAwareBeanPostProcessor" class="springBeanTest.MyInstantiationAwareBeanPostProcessor">
14     </bean>
15 
16     <bean id="beanFactoryPostProcessor" class="springBeanTest.MyBeanFactoryPostProcessor">
17     </bean>
18     
19     <bean id="person" class="springBeanTest.Person" init-method="myInit"
20         destroy-method="myDestory" scope="singleton" p:name="张三" p:address="广州"
21         p:phone="15900000000" />
22 
23 </beans>
View Code

 

(6)开始测试:

技术图片
 1 package com.ly.demo.spring.bean;
 2 
 3 import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 
 5 public class BeanLifeCycle {
 6     public static void main(String[] args) {
 7         System.out.println("现在开始初始化容器");
 8         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 9         System.out.println("容器初始化成功!");
10         // 得到Person并使用
11         Person person = context.getBean("person", Person.class);
12         System.out.println(person.toString());
13 
14         System.out.println("现在开始关闭容器");
15         context.registerShutdownHook();
16     }
17 }
View Code

关闭容器使用的是实际是AbstractApplicationContext的钩子方法。

我们来看一下结果:

现在开始初始化容器
11:11:00.939 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1996cd68
11:11:01.312 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 4 bean definitions from class path resource [beans.xml]
11:11:01.407 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘beanFactoryPostProcessor‘
这是BeanFactoryPostProcessor实现类构造器!!!
BeanFactoryPostProcessor调用postProcessBeanFactory方法
11:11:01.490 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘beanPostProcessor‘
这是BeanPostProcessor实现类构造器!!!
11:11:01.490 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘instantiationAwareBeanPostProcessor‘
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!!
11:11:01.504 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘person‘
InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
【构造器】调用Person的构造器实例化
InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法
【注入属性】注入属性name
【注入属性】注入属性address
【注入属性】注入属性phone
【BeanNameAware接口】调用BeanNameAware.setBeanName()
【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!
【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
【init-method】调用<bean>的init-method属性指定的初始化方法
BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!
InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法
容器初始化成功!
Person{name=‘张三‘, address=‘上海‘, phone=‘13156788899}
现在开始关闭容器
11:11:01.738 [Thread-0] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@1996cd68, started on Fri Nov 08 11:11:00 CST 2019
【DisposableBean接口】调用DisposableBean.destroy()
【destroy-method】调用<bean>的destroy-method属性指定的销毁方法

 

 

Spring Bean的生命周期

标签:init   初始   proc   frame   destory   div   上下文   initial   sso   

原文地址:https://www.cnblogs.com/yybinger/p/11818975.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!