`
uule
  • 浏览: 6305312 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

Spring中Bean初始化实例【重要】

 
阅读更多

参考文章:

Spring Bean 生命周期

Spring容器-Bean的生命周期 

Spring开闭原则的表现-BeanPostProcessor扩展点-1

 

容器启动时

最先调用

        BeanFactoryPostProcessor

                        ->postProcessBeanFactory() 

 

getBean时

实例化之后调用

        InstantiationAwareBeanPostProcessor

                ->postProcessPropertyValues()

 

初始化时

        属性注入(setter)

 

        BeanNameAware

                ->setBeanName() 

        BeanFactoryAware

                ->setBeanFactory() 

        ApplicationContextAware

                ->setApplicationContext()

  

        BeanPostProcessor

               ->postProcessBeforeInitialization()

        InitializingBean

                ->afterPropertiesSet()

        init-method属性

        BeanPostProcessor

                ->postProcessAfterInitialization()

 

        DiposibleBean

                ->destory() 

        destroy-method属性

 

 

BeanFactoryPostProcessor 
	//Spring IoC容器允许BeanFactoryPostProcessor在容器实际实例化任何其它的bean之前读取配置元数据,并有可能修改它。
	//同时BeanFactoryPostProcessor的回调比BeanPostProcessor要早
	void postProcessBeanFactory(ConfigurableListableBeanFactory arg) 	

	
InstantiationAwareBeanPostProcessorAdapter 
	其适配器类:InstantiationAwareBeanPostProcessor 
	
	//实例化Bean之前调用 (Bean构造函数前)
	Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
	
	//实例化Bean之后调用 
	boolean postProcessAfterInstantiation(Object bean, String beanName)
		
	PropertyValues postProcessPropertyValues(PropertyValues pvs,  
            PropertyDescriptor[] pds, Object bean, String beanName) 
	
	
BeanPostProcessor 
	//实例化、依赖注入完毕,在初始化之前调用,完成一些定制的初始化任务  
	Object postProcessBeforeInitialization(Object bean, String beanName)
	
	//实例化、依赖注入、初始化完毕时执行  
	Object postProcessAfterInitialization(Object bean, String beanName) 

 BeanFactoryPostProcessor和BeanPostProcessor都是Spring初始化bean的扩展点。两个接口非常相似。

BeanFactoryPostProcessor可以在postProcessBeanFactory()中对bean的定义(配置元数据)进行处理,而BeanPostProcessor不可以。

同时BeanFactoryPostProcessor的回调比BeanPostProcessor要早。

 http://blog.csdn.net/mn11201117/article/details/24986325

http://blog.csdn.net/xiao_jun_0820/article/details/7242379

 

实例1:

百度文库:

spring bean的生命周期是怎样的

  

实例2(重要):

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

1、Bean自身的方法:

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

 

2、Bean级生命周期接口方法:

  这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

 

3、容器级生命周期接口方法:

  这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

 

4、工厂后处理器接口方法:

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

 

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

1、首先是一个简单的Spring Bean,调用Bean自身的方法和Bean级生命周期接口方法,

为了方便演示,它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,

【对于BeanFactoryAware和BeanNameAware接口,第一个接口让bean感知容器(即BeanFactory实例,从而以此获取该容器配置的其他bean对象),而后者让bean获得配置文件中对应的配置名称。在一般情况下用户不需要关心这两个接口。如果bean希望获得容器中的其他bean,可以通过属性注入的方式引用这些bean。如果bean希望在运行期获知在配置文件中的Bean名称,可以简单的将名称作为属性注入

综上所述,我们认为除非编写一个基于spring之上的扩展框架插件或者子项目之类的东西,否则用户完全可以抛开以上4个bean生命周期的接口类

 

但BeanPostProcessor接口却不一样,它不要求bean去继承它,它可以完全像插件一样注册到spring容器中,为容器提供额外的功能。spring充分利用了BeanPostProcessor对bean进行加工处理(SpringAOP以此为基础)

 

同时有2个方法,对应配置文件中<bean>的init-method和destroy-method。如下:

 

package springBeanTest;
  
  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.DisposableBean;
  import org.springframework.beans.factory.InitializingBean;
  

 public class Person implements BeanFactoryAware, BeanNameAware,
         InitializingBean, DisposableBean {
 
     private String name;
     private String address;
     private int phone;
 
     private BeanFactory beanFactory;
     private String beanName;
 
     public Person() {
         System.out.println("【构造器】调用Person的构造器实例化");
     }
 
     public String getName() {
         return name;
     }
 
     public void setName(String name) {
         System.out.println("【注入属性】注入属性name");
         this.name = name;
     }
 
     public String getAddress() {
         return address;
     }
 
     public void setAddress(String address) {
         System.out.println("【注入属性】注入属性address");
         this.address = address;
     }
 
     public int getPhone() {
         return phone;
     }
 
     public void setPhone(int phone) {
         System.out.println("【注入属性】注入属性phone");
         this.phone = phone;
     }
 
     @Override
     public String toString() {
         return "Person [address=" + address + ", name=" + name + ", phone="
                 + phone + "]";
     }
 
     // 这是BeanFactoryAware接口方法
     @Override
     public void setBeanFactory(BeanFactory arg) throws BeansException {
         System.out
                 .println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
         this.beanFactory = arg;
     }
 
     // 这是BeanNameAware接口方法
     @Override
     public void setBeanName(String arg) {
         System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
         this.beanName = arg;
     }
 
     // 这是InitializingBean接口方法
     @Override
     public void afterPropertiesSet() throws Exception {
         System.out
                 .println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
     }
 
     // 这是DiposibleBean接口方法
     @Override
     public void destroy() throws Exception {
         System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
     }
 
     // 通过<bean>的init-method属性指定的初始化方法
     public void myInit() {
         System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
     }
 
     // 通过<bean>的destroy-method属性指定的初始化方法
     public void myDestory() {
         System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
     }
 }
  

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

 

 package springBeanTest;
  
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.config.BeanPostProcessor;
  
  public class MyBeanPostProcessor implements BeanPostProcessor {
  
      public MyBeanPostProcessor() {
         super();
         System.out.println("这是BeanPostProcessor实现类构造器!!");         
     }
 
     @Override
     public Object postProcessAfterInitialization(Object arg, String arg)
             throws BeansException {
         System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");
         return arg;
     }
 
     @Override
     public Object postProcessBeforeInitialization(Object arg, String arg)
             throws BeansException {
         System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");
         return arg;
     }
 }

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

  

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

 

 package springBeanTest;
  
  import java.beans.PropertyDescriptor;  
  import org.springframework.beans.BeansException;
  import org.springframework.beans.PropertyValues;
  import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
  
  public class MyInstantiationAwareBeanPostProcessor extends
         InstantiationAwareBeanPostProcessorAdapter {
 
     public MyInstantiationAwareBeanPostProcessor() {
         super();
         System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
     }
 
     // 接口方法、实例化Bean之前调用
     @Override
     public Object postProcessBeforeInstantiation(Class beanClass,
             String beanName) throws BeansException {
	     
         System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");
         return null;
     }
 
     // 接口方法、实例化Bean之后调用
     @Override
     public Object postProcessAfterInitialization(Object bean, String beanName)
             throws BeansException {
         System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");
         return bean;
     }
 
     // 接口方法、设置某个属性时调用
     @Override
     public PropertyValues postProcessPropertyValues(PropertyValues pvs,
             PropertyDescriptor[] pds, Object bean, String beanName)
             throws BeansException {
         System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");
         return pvs;
     }
 }

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

  

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

 

 package springBeanTest;
  
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.config.BeanDefinition;
  import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
  import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
  
  public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
  
     public MyBeanFactoryPostProcessor() {
         super();
         System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
     }
 
     @Override
     public void postProcessBeanFactory(ConfigurableListableBeanFactory arg)
             throws BeansException {
         System.out
                 .println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
         BeanDefinition bd = arg.getBeanDefinition("person");
         bd.getPropertyValues().addPropertyValue("phone", "");
     } 
 }

 

5、配置文件如下beans.xml,很简单,使用ApplicationContext,处理器不用手动注册:

 

<?xml version="1.0" encoding="UTF-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
 
    <bean id="beanPostProcessor" class="springBeanTest.MyBeanPostProcessor"></bean>
 
    <bean id="instantiationAwareBeanPostProcessor" class="springBeanTest.MyInstantiationAwareBeanPostProcessor"></bean>
 
    <bean id="beanFactoryPostProcessor" class="springBeanTest.MyBeanFactoryPostProcessor">
    </bean>
    
    <bean id="person" class="springBeanTest.Person" init-method="myInit"
        destroy-method="myDestory" scope="singleton" p:name="张三" p:address="广州"
        p:phone="15900000000" /> 
</beans>

 

6.测试 

 package springBeanTest;
  
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;
  
  public class BeanLifeCycle {
  
      public static void main(String[] args) {
  
         System.out.println("现在开始初始化容器");
         
         ApplicationContext ctx = new ClassPathXmlApplicationContext("springBeanTest/beans.xml");
         System.out.println("容器初始化成功");    
	 
         //得到Preson,并使用
         Person person = ctx.getBean("person",Person.class);
         System.out.println(person);
         
         System.out.println("现在开始关闭容器!");
         ((ClassPathXmlApplicationContext)ctx).registerShutdownHook();
     }
 }

 

结果如下:

现在开始初始化容器

2014-5-18 15:46:20 org.springframework.context.support.AbstractApplicationContext prepareRefresh

信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@19a0c7c: startup date [Sun May 18 15:46:20 CST 2014]; root of context hierarchy

2014-5-18 15:46:20 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions

信息: Loading XML bean definitions from class path resource [springBeanTest/beans.xml]

 

这是BeanFactoryPostProcessor实现类构造器!

BeanFactoryPostProcessor调用postProcessBeanFactory方法

这是BeanPostProcessor实现类构造器!!

这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!

 

2014-5-18 15:46:20 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons

信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9934d4: defining beans [beanPostProcessor,instantiationAwareBeanPostProcessor,beanFactoryPostProcessor,person]; root of factory hierarchy

 

InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法

【构造器】调用Person的构造器实例化

InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法

【注入属性】注入属性address

【注入属性】注入属性name

【注入属性】注入属性phone

【BeanNameAware接口】调用BeanNameAware.setBeanName()

【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()

BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!

【InitializingBean接口】调用InitializingBean.afterPropertiesSet()

【init-method】调用<bean>的init-method属性指定的初始化方法

BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!

InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法(这个位置感觉有问题,待解决)

容器初始化成功

Person [address=广州, name=张三, phone=110]

现在开始关闭容器!

【DiposibleBean接口】调用DiposibleBean.destory()

【destroy-method】调用<bean>的destroy-method属性指定的初始化方法 

 

图示如下:


 

 

 

 

  • 大小: 66.5 KB
分享到:
评论

相关推荐

    Spring Bean的初始化和销毁实例详解

    主要介绍了Spring Bean的初始化和销毁,结合实例形式详细分析了Spring Bean的初始化和销毁相关配置、使用方法及操作注意事项,需要的朋友可以参考下

    Spring bean初始化及销毁你必须要掌握的回调方法.docx

    3、通过spring的xml bean配置或bean注解指定初始化方法,如下面实例的initMethod方法通过@bean注解指定。 销毁的时候实现的方法 1、通过java提供的@PreDestroy注释; 2、通过实现spring提供的DisposableBean接口,并...

    Spring 延迟实例化

    Spring 延迟实例化

    spring001 基于xml的DI bean实例调用的是无参构造,如果需要bean对象的属性进行初始化

    spring核心:iOC Aop IOC:inverson of control(控制反转): 就是对对象控制权的转移,从程序代码本身反转到 外部容器中,通过外部容器实现对象的创建,属性 ...创建spring的配置文件,编写bean 4.在测试类中测试

    spring源码底层解析(1.81G)

    【课程介绍】:Spring启动时读取应用提供的Bean配置信息,在Spring容器中生成对应的Bean配置注册表...从源码证明springbean的实例化过程.mp44.spring的核心getSingleton方法.mp45.springbean的生成与循环依赖.mp46.getB

    基于java的企业级应用开发:Bean的生命周期.ppt

    (6)如果BeanPostProcessor和Bean关联,则Spring将调用该接口的预初始化方法postProcessBeforeInitialzation()对Bean进行加工操作,这个非常重要,Spring的AOP就是用它实现的。 (7)如果Bean实现了...

    08-IoC配置-bean的生命周期控制

    Spring IOC容器可以管理Bean的生命周期,允许在Bean生命周期的特定点执行定制的任务。 Spring IOC容器对Bean的生命周期...在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法。

    深入解析Spring IoC源码:核心机制与实践应用

    本文深入探讨了Spring框架中IoC容器的源码机制,涵盖了容器的初始化、Bean工厂的实例化、Bean定义的读取及Spring Bean的生命周期管理。通过精细的分析,本文揭示了AnnotationConfigApplicationContext的实例化过程,...

    深入解析Spring IoC:源码与实践指南

    同时,本文还探讨了Spring Bean的生命周期,重点在于Bean容器的创建与Bean的初始化过程。这些深入的分析不仅有助于理解Spring的内部工作机制,而且对于Java开发者来说,能够更好地掌握如何有效地使用Spring框架进行...

    Spring-Reference_zh_CN(Spring中文参考手册)

    3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.6.1. 设置Bean使自动装配失效 3.3.7. 依赖检查 3.3.8. 方法注入 3.3.8.1. Lookup方法注入 3.3.8.2. 自定义方法的替代方案 3.4. bean的作用域 3.4.1. ...

    Spring中文帮助文档

    3.3.4. 延迟初始化bean 3.3.5. 自动装配(autowire)协作者 3.3.6. 依赖检查 3.3.7. 方法注入 3.4. Bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. Singleton beans和prototype-bean的...

    Spring系列之依赖注入的三种方式.docx

    对于spring配置一个bean时,如果需要给该bean提供一些初始化参数,则需要通过依赖注入方式,所谓的 依赖注入就是通过spring将bean所需要的一些参数传递到bean实例对象的过程(将依赖关系注入到对象中) ,spring的...

    JAVA spring 系列案例50个和学习资料

    Spring系列第12篇:lazy-init:bean延迟初始化Spring系列第13篇:使用继承简化bean配置(abstract & parent)Spring系列第14篇:lookup-method和replaced-method比较陌生,怎么玩的?Spring系列第15篇:代理详解(Java...

    spring.doc

    Lazy-init初始化bean的时机拓展: 15 3.4 Bean的作用域 16 Scope单例多例作用域拓展: 16 3.4.1 singleton(默认值) 16 3.4.2 prototype 17 3.4.3 Request 17 3.4.4 Session 18 3.4.5 Global session 18 3.4.6 指定...

    Spring 中文API&开发文档.rar

    你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。 ◆面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务...

    开源框架面试专题及答案.pdf

    在一个 bean 实例被初始化时,需要执行一系列的初 始化操作以达到可用的状态。同样的,当一个 bean 不在被调用时需要进行相关的析构操 作,并从 bean 容器中移除。 &gt; Spring bean factory 负责管理在 spring 容器中...

    Spring 3 Reference中文

    4.4.4 延迟初始化bean . 55 4.4.5 自动装配协作者.. 55 4.4.5.1 自动装配的限制和缺点.. 56 4.4.5.2 从自动装配中排除bean. 57 4.4.6 方法注入. 57 4.4.6.1 查找方法注入.. 58 4.4....

    2024年Java高工面试题 2024年Java高工面试题 2024年Java高工面试题

    2024年Java高工面试题 JVM虚拟机:堆、方法区(元空间)、栈(线程)、本地方法栈、程序计数器 ...推断构造方法、实例化、属性填充、初始化前、初始化、初始化后等其中AOP就是发生在初始化后这一步

    Spring攻略(第二版 中文高清版).part1

    2.7 自定义Bean初始化和析构 72 2.7.1 问题 72 2.7.2 解决方案 72 2.7.3 工作原理 72 2.8 用Java Config简化XML配置 77 2.8.1 问题 77 2.8.2 解决方案 77 2.8.3 工作原理 77 2.9 使Bean感知容器 ...

Global site tag (gtag.js) - Google Analytics