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.
上半部分
下半部分