`
dylan0514sina.cn
  • 浏览: 95718 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

AbstractBeanFactory获取bean周期

 
阅读更多
AbstractBeanFactory是IOC容器实现的骨架,当从Spring容器获取Bean时,调用的正是getBean方法。实现步骤如下
  检查单例缓存
  在父工厂中查找
  初始化当前bean依赖的beans(depends-on)
  根据scope使用不同的创建方式bean
  检查获取的bean是FactoryBean类型还是普通bean
  可能的类型转换

  单例缓存
  spring中单例理解不同与设计模式中的单例,前者指一个容器对应类只有一个实例,后者指一个classloader有一个实例。Spring bean工厂将scope="singleton"的实例缓存到map中,下次查询时可从缓存缓存中取。对于这种scope的创建大致可用下图描述


  父工厂
   spring bean工厂可有父子关系,当前工厂中找不到时可从父工厂中查找,这也说明了每个工厂都有它对应的单例缓存。而非设计模式JVM中的单例理解

   depends-on
   指定了bean之间的依赖关系,同时也指定了bean初始化的先后顺序,或如果是单例也指定销毁时的先后顺序:
   初始化:依赖的类都要先于指定类
   销毁:依赖的类要晚于指定类
   
   scope
  singleton  指定类对每个bean Factory只有一个实例,生命周期完全有由spring容器管理,包括初始化时的回调和销毁时的回调
  prototype 每次请求都会创建一个新的实例,spring不会记录实例状态,也不负责销毁,即支持初始化回调,不支持销毁时的回调。客户端必须负责清理资源,可以使用初始化时的bean post-processor保存引用以便后续销毁。
  custom scope bean工厂支持注册自定义scope,可在初始化时由beanFactoryPostProcessor回调完成。AbstractApplicationContext提供了模版在所有beanFactoryPostprocessor之前修改bean定义,在其子类AbstractRefreshableWebApplicationContext的该方法实现如下,可以看到requestScope,sessionScope的实现
	/**
	 * Register ServletContextAwareProcessor.
	 * @see ServletContextAwareProcessor
	 */
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		beanFactory.registerScope(SCOPE_REQUEST, new RequestScope());
		beanFactory.registerScope(SCOPE_SESSION, new SessionScope(false));
		beanFactory.registerScope(SCOPE_GLOBAL_SESSION, new SessionScope(true));

		beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
		beanFactory.ignoreDependencyInterface(ServletContextAware.class);
		beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
	}

 我们自定义实现可以使用org.springframework.beans.factory.config.CustomScopeConfigurer负责注册。自定义Scope许扩展 org.springframework.beans.factory.config.Scope接口,如SimpleMapScope。
/*
 * Copyright 2002-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.ObjectFactory;

/**
 * @author Juergen Hoeller
 */
public class SimpleMapScope implements Scope, Serializable {

	private final Map map = new HashMap();

	private final List callbacks = new LinkedList();


	public SimpleMapScope() {
	}

	public final Map getMap() {
		return this.map;
	}


	public Object get(String name, ObjectFactory objectFactory) {
		synchronized (this.map) {
			Object scopedObject = this.map.get(name);
			if (scopedObject == null) {
				scopedObject = objectFactory.getObject();
				this.map.put(name, scopedObject);
			}
			return scopedObject;
		}
	}

	public Object remove(String name) {
		synchronized (this.map) {
			return this.map.remove(name);
		}
	}

	public void registerDestructionCallback(String name, Runnable callback) {
		this.callbacks.add(callback);
	}

	public Object resolveContextualObject(String key) {
		return null;
	}

	public void close() {
		for (Iterator it = this.callbacks.iterator(); it.hasNext();) {
			Runnable runnable = (Runnable) it.next();
			runnable.run();
		}
	}

	public String getConversationId() {
		return null;
	}

}
   创建方式比较
   Spring实现中,不管是哪种创建实现方式都差不多,比如设置正在创建标志避免循环引用导致的内存溢出、最终通过Spring配置蓝图创建。单例的创建多了一些缓存的设置,prototype更简单直接调用createbean根据Spring配置蓝图创建;自定义scope调用get方法,最终还是使用Spring ObjectFactory创建蓝图。
   
   检查bean FactoryBean
   当bean得到之后,必须进行合理的检查才能使用。
   如果bean是FactoryBean实例,检索的bean id 是以"&"开头直接返回
   如果bean是FactoryBean实例,检索的bean id不是"&"开头,调用Factorybean的getObject方法
   如果bean不是FactoryBean实例,检索的bean id 是以"&"开头,报错
   如果bean不是FactoryBean实例,检索的bean idb不是以"&"开头,返回
 
   短路shut-cut
   Spring容器给了InstantiationAwareBeanPostProcessor机会在Bean根据Spring配置创建之前执行回调,如果返回不会空则getBean终止:
   postProcessBeforeInstantiation 回调实例化之前调用,返回值不为空则执行
   BeanPostProcessor的applyBeanPostProcessorsAfterInitialization方法
   
   创建实例
   1.使用适当的实例化策略:工厂方法,构造器装配,反射newInstance创建内存对象
   2.可能的MergedBeanDefinitionPostProcessor注解处理
   3.可能的singletonFactory创建
   4.装配bean
  5.调用初始化方法及beanPostProcessor方法
   6.如果在beanPostProcessor实现中改变了传入bean的地址,比如自动代理将会创建一个新的地址返回,则会报错org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bean1': Bean with name 'bean1' has been injected into other beans [bean2] in its raw version as part of a circular reference, but has eventually been wrapped (for example as part of auto-proxy creation). This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.

上半部分

下半部分


0
1
分享到:
评论

相关推荐

    spring bean的循环依赖完全掌握.pdf

    为了彻底掌握 Spring Bean 的循环依赖,我们需要搞清楚四个问题:普通 Bean 的非循环依赖 Bean 生命周期的流程、AOP 代理 Bean 的非循环依赖 Bean 生命周期的流程、普通 Bean 的循环依赖 Bean 生命周期的流程和 AOP ...

    Spring Bean创建初始化流程.docx

    5. **获取Bean实例**: 在预实例化过程中,`getBean(beanName)`被调用,这是`AbstractBeanFactory`类中的一个方法,用于从Bean工厂中获取指定名称的Bean实例。 6. **实际获取Bean**: 进入`doGetBean()`方法,这...

    spring 源码分析

    在BeanFactory中定义的接口中,最基本的操作包括根据bean的名字获取bean实例、根据bean名字和类型获取bean实例、检查容器中是否存在指定名称的bean、检查bean实例是否为单例模式、获取bean的类型、获取bean的别名等...

    spring 原码解析 spring 原码解析

    BeanFactory是Spring框架中最基本的IOC容器接口,它定义了用于管理bean的标准方法集,包括获取bean、判断bean是否存在等功能。尽管BeanFactory非常基础,但它为构建更复杂的容器奠定了坚实的基础。 - **接口定义**...

    spring源代码中文详解版

    BeanFactory接口提供了几个关键方法,例如`getBean(String name)`用于根据bean的名称获取bean实例;`getBean(String name, Class requiredType)`则在获取bean时,确保返回的实例与指定类型匹配。`containsBean...

    【课堂笔记】一步一步手绘Spring+DI运行时序图.pdf

    `AbstractBeanFactory`是`BeanFactory`的一个实现,包含了实际获取Bean的逻辑。`getBean()`方法是用户获取Bean的主要途径,而`doGetBean()`方法则是实现依赖注入的关键。 在`AbstractBeanFactory`中,`doGetBean()`...

    Spring IOC设计原理解析.docx

    3. `FactoryBean`允许自定义Bean的创建逻辑,`AbstractBeanFactory`在获取Bean时会检查是否是FactoryBean并调用其`getObject()`方法。 4. `BeanPostProcessor`可以定制Bean实例化后的处理,`...

    spring源码解析

    `BeanFactory`接口是Spring框架中IOC容器的基础接口,它提供了对容器中Bean的基本操作,如获取Bean、检查Bean是否存在、判断Bean是否为单例等。以下是该接口中关键方法的详细介绍: 1. **`getBean(String name)`**:...

    Spring源代码自我解析

    在Spring中,BeanFactory是最基础的IoC容器接口,定义了容器的基本功能,如根据Bean名称获取Bean实例、检查Bean是否存在、判断Bean是否为单例等。 ##### BeanFactory接口详解 BeanFactory接口中包含了几个关键方法...

    Spring源代码解析(一):IOC容器.doc

    BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的类型以及获取Bean的别名。以下是对BeanFactory接口中关键方法的解释: 1. `getBean(String name)`:此方法根据...

    Spring源码分析

    BeanFactory通过资源抽象定义了对Bean的获取,这包括通过名称获取Bean实例、通过类型获取Bean实例、检查容器中是否存在指定的Bean等。BeanFactory接口之所以不关心Bean的定义和加载过程,是因为它是一个抽象工厂,其...

    Spring DI原理.docx

    `BeanFactory`接口是Spring IoC容器的基础,它定义了获取Bean的基本方法。`AbstractBeanFactory`作为`BeanFactory`的一个实现,是理解依赖注入机制的关键。 `AbstractBeanFactory`中的`getBean()`方法系列,如`...

    Spring ioc源码解读

    - **BeanFactory**:这是Spring提供的最基础的IoC容器接口,定义了一些用于获取Bean实例的基础方法。如`getBean`用于获取指定名称的Bean实例;`containsBean`用于检查是否存在指定名称的Bean;`isSingleton`用于判断...

    spring 源码解析

    XmlBeanFactory 基于 AbstractBeanFactory 抽象类,后者通过 Resource 接口抽象了 bean 定义的数据来源,而具体的解析工作由 XmlBeanDefinitionReader 完成。 Spring 的容器不仅仅局限于 BeanFactory,还有 ...

    详解Spring中Bean的加载的方法

    ` 这一行代码就是请求Spring容器创建或获取名为"testBean"的Bean实例。这个过程实际上是由`AbstractBeanFactory`类的`doGetBean`方法来处理的。 `doGetBean`方法的主要逻辑如下: 1. **缓存检查**:Spring容器会先...

    简单Spring框架模拟器--Demo

    接着,“tiny-spring-step-2-abstract-beanfactory-and-do-bean-initilizing-in-it.zip”进一步深入,介绍了AbstractBeanFactory和Bean的初始化过程。在这个阶段,你将学习到BeanFactory如何解析XML配置,创建Bean...

    1000行代码读懂Spring核心

    通过创建抽象类AbstractBeanFactory来实现对Bean生命周期的管理,并在内部进行Bean的初始化。 #### step-3:属性注入 第三个步骤是通过PropertyValues类来保存属性注入信息,并通过AutowireCapableBeanFactory实现...

Global site tag (gtag.js) - Google Analytics