文档章节

Spring学习总结1——bean的生命周期

yope
 yope
发布于 2015/02/26 09:32
字数 1908
阅读 80
收藏 3
点赞 0
评论 0

   Spring实际上是一个容器框架,可以配置各种bean(action/service/domain/dao...),并且可以维护bean与bean的关系。

ioc是什么?

答 :ioc(inverse of controll ) 控制反转所谓控制反转就是把创建对象(bean),和维护对象(bean)的关系的权利从程序中转移到spring的容器(applicationContext.xml),而程序本身不再维护

DI是什么?

: di(dependency injection) 依赖注入实际上diioc是同一个概念,spring设计者认为di更准确表示spring核心技术。

下面以BeanFactory为例,说明一个Bean的生命周期活动:

1.Bean的建立

      由BeanFactory读取Bean定义文件,并生成各个实例。

2.Setter注入

      执行Bean的属性依赖注入。

3.BeanNameAware的setBeanName()

      如果Bean类实现了org.springframework.beans.factory.BeanNameAware接口,则执行其setBeanName()方法。

4.BeanFactoryAware的setBeanFactory()

      如果Bean类实现了org.springframework.beans.factory.BeanFactoryAware接口,则执行其setBeanFactory()方法。

5.BeanPostProcessors的processBeforeInitialization()

      容器中如果有实现org.springframework.beans.factory.BeanPostProcessors接口的实例,则任何Bean在初始化之前都会执行这个实例的processBeforeInitialization()方法。

6.InitializingBean的afterPropertiesSet()

      如果Bean类实现了org.springframework.beans.factory.InitializingBean接口,则执行其afterPropertiesSet()方法。

7.Bean定义文件中定义init-method

      在Bean定义文件中使用“init-method”属性设定方法名称,如下:

<bean id="demoBean" class="com.nyp.bean.DemoBean" init-method="initMethod">
  .......
 </bean>

      这时会执行initMethod()方法,注意,这个方法是不带参数的。

8.BeanPostProcessors的processAfterInitialization()

      容器中如果有实现org.springframework.beans.factory.BeanPostProcessors接口的实例,则任何Bean在初始化之前都会执行这个实例的processAfterInitialization()方法。

9.DisposableBean的destroy()

      在容器关闭时,如果Bean类实现了org.springframework.beans.factory.DisposableBean接口,则执行它的destroy()方法。

10.Bean定义文件中定义destroy-method

      在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法

<bean id="demoBean" class="com.nyp.bean.DemoBean" destory-method="destroyMethod">
  .......
</bean>

       这时会执行destroyMethod()方法,注意,这个方法是不带参数的。

   以上就是BeanFactory维护的一个Bean的生命周期。下面这个图可能更直观一些:

如果使用ApplicationContext来维护一个Bean的生命周期,则基本上与上边的流程相同,只不过在执行BeanNameAware的setBeanName()后,若有Bean类实现了org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,然后再进行BeanPostProcessors的processBeforeInitialization()

   实际上,ApplicationContext除了向BeanFactory那样维护容器外,还提供了更加丰富的框架功能,如Bean的消息,事件处理机制等。

小结: 我们实际开发中往往,没有用的这么的过程,常见的是:

  1.  实例化

  2. 调用set方法设置属性

  3. 如果bean 和 一个前置处理器关联

  4. 使用我们的bean

  5. 如果bean 和 一个后置处理器关联

  6. 容器关闭

在这里在补充讲一下BeanFactory(Spring心脏) 与ApplicationContext(身躯)比较:

BeanFactory在初始化容器的时候,并未实例化Bean,直到第一次访问Bean时才实例化目标Bean;

ApplicationContext在初始化应用上下文时就实例化所有单实例的Bean(所以初始化比较耗时,不过稍后使用不存在“第一次惩罚”)

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

1、Bean自身的方法 : 

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

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

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

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

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

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

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

最后来个演示:

首先是一个bean User

package com.sunsharing.beanlife;

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.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * Created by nyp on 2015/2/27.
 */
public class User implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{
    private String name;
    private Integer age;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        System.out.println("属性age set方法:setName(Integer age) 被调用");
        this.age = age;
    }

    public String getName() {
        return name;
    }
    
     public void setName(String name) {
        System.out.println("属性name set方法:setName(String name) 被调用");
        this.name = name;
    }
    public User(){
        System.out.println("构造函数:User ");
    }

    public void sayHi(){
        System.out.println("hi "+ name);
    }

    //该方法可以给arg0表示正在被实例化得bean id
    public void setBeanName(String arg0) {
        // TODO Auto-generated method stub
        System.out.println("BeanNameAware接口:setBeanName 被调用 值"+arg0);
    }
    //该方法可以传递beanFactroy
    public void setBeanFactory(BeanFactory arg0) throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("BeanFactoryAware接口:setBeanFactory 被调用"+arg0);
    }
    //该方法传递ApplicationContext
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("ApplicationContextAware接口:setApplicationContext "+arg0);
    }

    //这是InitializingBean接口方法
    public void afterPropertiesSet() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("InitializingBean接口:InitializingBean.afterPropertiesSet()");
    }
    // 这是DiposibleBean接口方法
    public void destroy() throws Exception {
              System.out.println("DiposibleBean接口:调用DiposibleBean.destory()");
    }

   //定制我们的初始化方法
    public void myinit(){
        System.out.println("自定义myinit方法 被调用");
    }
    //定制我们的销毁方法
       public void mydestory(){
        System.out.println("自定义mydestory 释放各种资源");
    }

}

然后是MyBeanPostProcessor

package com.sunsharing.beanlife;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * Created by nyp on 2015/2/27.
 */
public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object arg0, String arg1)
            throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("BeanPostProcessor接口:postProcessAfterInitialization 函数被调用   "+arg0+"被创建的时间是"+new java.util.Date());
        return arg0;
    }
    public Object postProcessBeforeInitialization(Object arg0, String arg1)
            throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("BeanPostProcessor接口:postProcessBeforeInitialization 函数被调用");
        return arg0;
    }
}

接着ApplicatationContext.xml的配置

<?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:context="http://www.springframework.org/schema/context"
      xmlns:tx="http://www.springframework.org/schema/tx"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
   <bean id="personService" init-method="myinit" destroy-method="mydestory"  class="com.sunsharing.beanlife.User"  >
      <!-- 这里注入我们属性,前提就是有setName才能ok -->
      <property name="name">
         <value>小明</value>
      </property>
      <property name="age">
         <value>2015</value>
      </property>
   </bean>
   <!-- 配置我们的自己后置处理器(有点类似我们的filter) -->
   <bean id="myBeanPostProcessor" class="com.sunsharing.beanlife.MyBeanPostProcessor" />
</beans>

最后用一个App类 测试下,

package com.sunsharing.beanlife;

/**
 * Created by nyp on 2015/2/27.
 */
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("==========开始初始化容器!==========");
        BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("==========初始化成功!==========");
        User u=(User) factory.getBean("personService");
        u.sayHi();
        System.out.println("==========开始关闭容器!==========");
        ((ClassPathXmlApplicationContext)factory).registerShutdownHook();
    }

}

然后华丽丽的结果出来了,如下:

==========开始初始化容器!==========
[INFO ] [22:22:15] org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7b7381ef: startup date [Fri Feb 27 22:22:15 CST 2015]; root of context hierarchy
[INFO ] [22:22:15] org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml]
[INFO ] [22:22:17] org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@229a8e52: defining beans [personService,myBeanPostProcessor]; root of factory hierarchy
构造函数:User 
属性name set方法:setName(String name) 被调用
属性age set方法:setName(Integer age) 被调用
BeanNameAware接口:setBeanName 被调用 值personService
BeanFactoryAware接口:setBeanFactory 被调用org.springframework.beans.factory.support.DefaultListableBeanFactory@229a8e52: defining beans [personService,myBeanPostProcessor]; root of factory hierarchy
ApplicationContextAware接口:setApplicationContext org.springframework.context.support.ClassPathXmlApplicationContext@7b7381ef: startup date [Fri Feb 27 22:22:15 CST 2015]; root of context hierarchy
BeanPostProcessor接口:postProcessBeforeInitialization 函数被调用
InitializingBean接口:InitializingBean.afterPropertiesSet()
自定义myinit方法 被调用
BeanPostProcessor接口:postProcessAfterInitialization 函数被调用   com.sunsharing.beanlife.User@fc85b94被创建的时间是Fri Feb 27 22:22:17 CST 2015
==========初始化成功!==========
hi 小明
==========开始关闭容器!==========
[INFO ] [22:22:17] org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@7b7381ef: startup date [Fri Feb 27 22:22:15 CST 2015]; root of context hierarchy
[INFO ] [22:22:17] org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@229a8e52: defining beans [personService,myBeanPostProcessor]; root of factory hierarchy
DiposibleBean接口:调用DiposibleBean.destory()
自定义mydestory 释放各种资源
Process finished with exit code 0

这样打印的结果清晰明了,相信对理解spring bean生命周期的理解会更加深刻。


© 著作权归作者所有

共有 人打赏支持
yope
粉丝 15
博文 38
码字总数 33640
作品 0
厦门
程序员
Spring基础篇——Spring容器和应用上下文理解

上文说到,有了Spring之后,通过依赖注入的方式,我们的业务代码不用自己管理关联对象的生命周期。业务代码只需要按照业务本身的流程,走啊走啊,走到哪里,需要另外的对象来协助了,就给Spr...

圆梦巨人 ⋅ 05/03 ⋅ 0

Spring系列之Spring常用注解总结

传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点: 1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么...

HJCui ⋅ 05/29 ⋅ 0

手把手教你搭建SpringMVC——最小化配置

为什么需要Spring MVC 最开始接触网页的时候,是纯的html/css页面,那个时候还是用Dreamweaver来绘制页面。 随着网站开发的深入,开始学习servlet开发,记得最痛苦的就是servlet返回网页的内...

青夜之衫 ⋅ 2017/12/05 ⋅ 0

说说在 Spring 中如何基于 Java 类进行配置

JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能 。 1 定义 Bean 普通的 POJO 只要标注...

deniro ⋅ 05/11 ⋅ 0

Aspectj与Spring AOP比较

1、简介 今天有多个可用的 AOP 库, 它们需要能够回答许多问题: 是否与用户现有的或新的应用程序兼容? 在哪里可以实现 AOP? 与自己的应用程序集成多快? 性能开销是多少? 在本文中, 我们将...

沈渊 ⋅ 04/18 ⋅ 0

spring4.0之二:@Configuration的使用

从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfi...

文文1 ⋅ 06/01 ⋅ 0

网关 Spring-Cloud-Gateway 源码解析 —— 网关初始化

网关 Spring-Cloud-Gateway 源码解析 —— 网关初始化 Harries Blog™2017-12-135 阅读 SpringAppclasspathcatbeanAPIbuildbug 本文主要基于 Spring-Cloud-Gateway 2.0.X M4 摘要: 原创出处 ......

Harries Blog™ ⋅ 2017/12/13 ⋅ 0

Spring之IoC(控制反转)和DI(依赖注入)

1.IoC的概念 IoC:通过容器去控制业务对象之间的依赖关系。控制权由应用代码中转到了外部容器,控制权的转移就是反转。控制权转移的意义是降低了类之间的耦合度。 Spring中将IoC容器管理的对...

Java攻城玩家 ⋅ 05/28 ⋅ 0

Spring中涉及的设计模式总结

Spring中涉及的设计模式总结 1.简单工厂(非23种设计模式中的一种) 实现方式:BeanFactory。 Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是...

caoxiaohong1005 ⋅ 04/22 ⋅ 0

Spring IOC知识点一网打尽!

前言 只有光头才能变强 回顾前面: 给女朋友讲解什么是代理模式 包装模式就是这么简单啦 单例模式你会几种写法? 工厂模式理解了没有? 在刷Spring书籍的时候花了点时间去学习了单例模式和工...

Java3y ⋅ 05/22 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

SpringCloud 微服务 (六) 服务通信 RestTemplate

壹 通信的方式主要有两种,Http 和 RPC SpringCloud使用的是Http方式通信, Dubbo的通信方式是RPC 记录学习SpringCloud的restful方式: RestTemplate (本篇)、Feign 贰 RestTemplate 类似 Http...

___大侠 ⋅ 9分钟前 ⋅ 0

React创建组件的三种方式

1.无状态函数式组建 无状态函数式组件,也就是你无法使用State,也无法使用组件的生命周期方法,这就决定了函数组件都是展示性组件,接收Props,渲染DOM,而不关注其他逻辑。 无状态函数式组...

kimyeongnam ⋅ 16分钟前 ⋅ 0

react 判断实例类型

今天在写组件的时候想通过判断内部子元素不同而在父元素上应用不同的class,于是首先要解决的就是如何判断子元素的类型。 这里附上一个讲的很全面的文章: https://www.cnblogs.com/onepixel...

球球 ⋅ 22分钟前 ⋅ 0

Centos7备份数据到百度网盘

一、关于 有时候我们需要进行数据备份,如果能自动将数据备份到百度网盘,那将会非常方便。百度网盘有较大的存储空间,而且不怕数据丢失,安全可靠。下面简单的总结一下如何使用 bypy 实现百...

zctzl ⋅ 36分钟前 ⋅ 0

开启远程SSH

SSH默认没有开启账号密码登陆,需要再配置表中修改: vim /etc/ssh/sshd_configPermitRootLogin yes #是否可以使用root账户登陆PasswordAuthentication yes #是都开启密码登陆ser...

Kefy ⋅ 39分钟前 ⋅ 0

Zookeeper3.4.11+Hadoop2.7.6+Hbase2.0.0搭建分布式集群

有段时间没更新博客了,趁着最近有点时间,来完成之前关于集群部署方面的知识。今天主要讲一讲Zookeeper+Hadoop+Hbase分布式集群的搭建,在我前几篇的集群搭建的博客中已经分别讲过了Zookeep...

海岸线的曙光 ⋅ 46分钟前 ⋅ 0

js保留两位小数方法总结

本文是小编针对js保留两位小数这个大家经常遇到的经典问题整理了在各种情况下的函数写法以及遇到问题的分析,以下是全部内容: 一、我们首先从经典的“四舍五入”算法讲起 1、四舍五入的情况...

孟飞阳 ⋅ 今天 ⋅ 0

python log

python log 处理方式 log_demo.py: 日志代码。 #! /usr/bin/env python# -*- coding: utf-8 -*-# __author__ = "Q1mi""""logging配置"""import osimport logging.config# 定义三种......

inidcard ⋅ 今天 ⋅ 0

mysql 中的信息数据库以及 shell 查询 sql

Information_schema 是 MySQL 自带的信息数据库,里面的“表”保存着服务器当前的实时信息。它提供了访问数据库元数据的方式。 什么是元数据呢?元数据是关于数据的数据,如数据库名或表名,...

blackfoxya ⋅ 今天 ⋅ 0

maven配置阿里云镜像享受飞的感觉

1.在maven目录下的conf/setting.xml中找到mirrors添加如下内容,对所有使用改maven打包的项目生效。 <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.al......

kalnkaya ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部