Spring IOC 是Spring最核心的东西,对Bean的管理是Spring的核心,而后其余功能都是在Bean容器基础上进行扩展的。Spring容器这块咱们重点介绍两个大块:一个是BeanFactory,一个是ApplicationContext。这二者的关系是包含关系,ApplicationContext包含了BeanFactory功能,同时又扩展了事件,消息,资源等方面的东西。java
从这个类图层级结构上看主要分为左右两大部分,左半部分主要定义了BeanFacotry相关的接口,右半部分主要定义了BeanRegistry相关的接口。git
从这个类图咱们自上而下逐布分析,该类图结构很清晰,通常是一个接口对应一个抽象类的相关实现,一直到最后进行融合都集中到DefaultListableBeanFactory。咱们先大致介绍上面的类图结构,而后在介绍下BeanDefinition,及BeanFactory工做流程。spring
BeanDefinitionRegistry:主要定义了BeanDefinition注册接口。这个接口的实现就是最后到DefaultListableBeanFactory才实现的。
数组
AliasRegistry:这个顶级接口主要是为了管理别名的。对应的实现类主要是SimpleAliasRegistry,内部维护了一个map,来维护对应的关系。ide
如今开始介绍BeanFactory主线方面的接口。工具
BeanFactory:这个Factory的顶级接口,主要定义了Factory最重要的接口,好比getBean等。测试
SingletonBeanRegistry:这个接口主要定义了单例bean管理相关的接口,如registerSingleton,getSingleton等。ui
HierarchicalBeanFactory:这个层级BeanFactory主要定义了BeanFactory能够包含父Factory功能的相关接口。this
ConfigurableBeanFactory:继承了HierarchicalBeanFactory,这个接口的做用主要是定义了一些Factory的配置接口,好比setBeanClassLoader,setParentBeanFactory,addBeanPostProcessor,等等。采用Builder模式,一步一步组装Factory。spa
ListableBeanFactory:这个接口的做用主要定义了如何枚举一个Factory中的相关类,而不是经过name一个一个去获取,好比该接口定了getBeanNamesForType,getBeanNamesForAnnotation,getBeansWithAnnotation等等,都是以数组,集合等方式返回多个知足需求的结果。
AutowireCapableBeanFactory:这个接口主要定义了建立bean,自动注入等相关的接口。
ConfigurableListableBeanFactory:这个接口从名字上看把ConfigurableBeanFactory,ListableBeanFactory,AutowireCapableBeanFactory三个结合融合在一块儿,并作了扩展主要提供了分析修改bean definitions的工具,和对单例bean的预实例化(preInstantiateSingletons)。这个接口能够说是上面介绍全部的接口大融合,涵盖了BeanFactory所需的大部分方法。
具体接口实现
DefaultSingletonBeanRegistry:这个类主要实现了SingletonBeanRegistry,定义了单例bean的注册获取功能。内部实现经过ConcurrentHashMap来维护bean实例。
FactoryBeanRegistrySupport:该类继承DefaultSingletonBeanRegistry,扩展了FactoryBean须要的相关方法。由于FactoryBean是一种特殊的SingletonBean。
AbstractBeanFactory:该类继承了FactoryBeanRegistrySupport,实现了接口ConfigurableBeanFactory定义的相关功能。
AbstractAutowireCapableBeanFactory:该类继承了AbstractBeanFactory,同时实现接口AutowireCapableBeanFactory相关功能。
DefaultListableBeanFactory:这个是总的BeanFactory的实现,同时它自己实现了BeanDefinitionRegistry接口定义的功能,并继承了AbstractAutowireCapableBeanFactory(主要对应ConfigurableListableBeanFactory接口的实现)。
这里提下XmlBeanFactory:该类扩展了DefaultListableBeanFactory,方便的从xml文档中读取bean definitions;该类借助XmlBeanDefinitionReader实现,做用等同于把XmlBeanDefinitionReader和DefaultListableBeanFactory简单的包装。
从上面三大块对类图结构的介绍咱们能够看到spring 采用接口细化,逐级继承,而后逐级实现相关功能。直到最后所有功能实现。结构清晰,利于扩展及复用。
这里先介绍下BeanDefinition。BeanDefinition主要描述了一个bean实例。包含范围(单例or原型),bean Class类型,实例的属性值,构造参数值等等,能够说是一个类须要实例化须要的基本元数据。咱们平时在xml配置的bean信息都会转变为BeanDefinition。AbstractBeanDefinition做为BeanDefinition 的抽象实现。而后该类有三个具体的实现类:
ChildBeanDefinition: Bean definition for beans which inherit settings from their parent. Child bean definitions have a fixed dependency on a parent bean definition.(直接从sping文档中摘取)
RootBeanDefinition: A root bean definition represents the merged bean definition that backs a specific bean in a Spring BeanFactory at runtime. It might have been created from multiple original bean definitions that inherit from each other, typically registered as GenericBeanDefinition . A root bean definition is essentially the 'unified' bean definition view at runtime.(主要是spring运行时内部能够用来合并多个definition)
GenericBeanDefinition:一站式标准的bean definition。像任何bean definition,它容许为指定的类添加构造参数值和属性值。而且能够指定parentName,灵活的从父Bean definition进行派生。通常来讲,用GenericBeanDefinition用来注册用户可见的bean definition。父子关系须要预约义的地方 RootBeanDefinition/ChildBeanDefinition。
这里若是读者想本身调试运行代码 能够直接git clone spring源码,而后按照导入说明导入便可,不过加载的时间很长。
咱们先定义个class
//先定义一个普通的java类 public class Person { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } //测试代码 @Test public void testPerson() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); //用Properties拼装出BeanDefinitions所需的参数值。 Properties p = new Properties(); p.setProperty("yao.(class)", Person.class.getName()); p.setProperty("yao.age", "18"); p.setProperty("yao.name", "robin"); //把p转化为beanDefinition并注册到beanFactory中。 //若是不写scope,beanFactory默认产生单例bean。 (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p); Person p1 = (Person) lbf.getBean("yao"); Person p2 = (Person) lbf.getBean("yao"); assertTrue("Non null", p1 != null); assertTrue("Singletons equal", p1 == p2); lbf = new DefaultListableBeanFactory(); p = new Properties(); p.setProperty("yao.(class)", Person.class.getName()); p.setProperty("yao.age", "18"); p.setProperty("yao.name", "robin"); //修改scope p.setProperty("yao.(scope)", "prototype"); (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p); p1 = (Person) lbf.getBean("yao"); p2 = (Person) lbf.getBean("yao"); assertTrue("Non null", p1 != null); assertTrue("Prototypes NOT equal", p1 != p2); }
bean生成的简单过程:先是经过参数值转化成BeanDefinition,注册到BeanFactory中,经过getBean获取具体实例。
下面咱们一步一步debug ,摘取重要代码:
第一步:registerBeanDefinitions
//类PropertiesBeanDefinitionReader public int registerBeanDefinitions(Map<?, ?> map, String prefix, String resourceDescription) throws BeansException { --------代码省略 具体可去看spring源码----- String keyString = (String) key; if (keyString.startsWith(prefix)) { --------代码省略 具体可去看spring源码----- if (sepIdx != -1) { //从property中截取咱们的beanName String beanName = nameAndProperty.substring(0, sepIdx); //判断咱们注册容器中是否有该bean if (!getRegistry().containsBeanDefinition(beanName)) { // If we haven't already registered it... registerBeanDefinition(beanName, map, prefix + beanName, resourceDescription); ++beanCount; } } --------代码省略 具体可去看spring源码----- } } return beanCount; } protected void registerBeanDefinition(String beanName, Map<?, ?> map, String prefix, String resourceDescription) throws BeansException { String className = null; String parent = null; //默认的scope 主要是这个代码 String scope = GenericBeanDefinition.SCOPE_SINGLETON; boolean isAbstract = false; //是否延迟初始化 boolean lazyInit = false; ConstructorArgumentValues cas = new ConstructorArgumentValues(); MutablePropertyValues pvs = new MutablePropertyValues(); //遍历咱们添写的属性值 name age 类名字等待。 for (Map.Entry<?, ?> entry : map.entrySet()) { String key = StringUtils.trimWhitespace((String) entry.getKey()); if (key.startsWith(prefix + SEPARATOR)) { String property = key.substring(prefix.length() + SEPARATOR.length()); //从map中解析咱们的className if (CLASS_KEY.equals(property)) { className = StringUtils.trimWhitespace((String) entry.getValue()); } else if (PARENT_KEY.equals(property)) { parent = StringUtils.trimWhitespace((String) entry.getValue()); } else if (ABSTRACT_KEY.equals(property)) { String val = StringUtils.trimWhitespace((String) entry.getValue()); isAbstract = TRUE_VALUE.equals(val); } //解析scope else if (SCOPE_KEY.equals(property)) { // Spring 2.0 style scope = StringUtils.trimWhitespace((String) entry.getValue()); } // else if (SINGLETON_KEY.equals(property)) { // Spring 1.2 style String val = StringUtils.trimWhitespace((String) entry.getValue()); scope = ((val == null || TRUE_VALUE.equals(val) ? GenericBeanDefinition.SCOPE_SINGLETON : GenericBeanDefinition.SCOPE_PROTOTYPE)); } else if (LAZY_INIT_KEY.equals(property)) { String val = StringUtils.trimWhitespace((String) entry.getValue()); lazyInit = TRUE_VALUE.equals(val); } //构造参数 else if (property.startsWith(CONSTRUCTOR_ARG_PREFIX)) { if (property.endsWith(REF_SUFFIX)) { int index = Integer.parseInt(property.substring(1, property.length() - REF_SUFFIX.length())); cas.addIndexedArgumentValue(index, new RuntimeBeanReference(entry.getValue().toString())); } else { int index = Integer.parseInt(property.substring(1)); cas.addIndexedArgumentValue(index, readValue(entry)); } } else if (property.endsWith(REF_SUFFIX)) { // This isn't a real property, but a reference to another prototype // Extract property name: property is of form dog(ref) property = property.substring(0, property.length() - REF_SUFFIX.length()); String ref = StringUtils.trimWhitespace((String) entry.getValue()); // It doesn't matter if the referenced bean hasn't yet been registered: // this will ensure that the reference is resolved at runtime. Object val = new RuntimeBeanReference(ref); pvs.add(property, val); } else { // 类实例自己须要的正常属性值 pvs.add(property, readValue(entry)); } } } --------代码省略 具体可去看spring源码----- if (parent == null && className == null && !beanName.equals(this.defaultParentBean)) { parent = this.defaultParentBean; } try { //经过utils工具建立一个GenericBeanDefinition AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition( parent, className, getBeanClassLoader()); //组装解析到的属性值 bd.setScope(scope); bd.setAbstract(isAbstract); bd.setLazyInit(lazyInit); bd.setConstructorArgumentValues(cas); bd.setPropertyValues(pvs); //注册到beanFactory中,这里的registry其实就是DefaultListableBeanFactory,添加到其维护的 //ConcurrentHashMap中 getRegistry().registerBeanDefinition(beanName, bd); } catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(resourceDescription, beanName, className, ex); } catch (LinkageError err) { throw new CannotLoadBeanClassException(resourceDescription, beanName, className, err); } }
第二步 获取bean
//类AbstractBeanFactory protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // 先去缓冲中取 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } //去父factory获取 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { --------代码省略 具体可去看spring源码----- return xxxxxx; } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { //前面提到的RootBeanDefinition 能够用来合并多个definition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. --------代码省略 具体可去看spring源码----- // Create bean instance. //单例 if (mbd.isSingleton()) { //先是去缓冲取,取不到在createBean,这里就不跟进去了层级还很深。主要是建立bean, //把咱们配置的属性值都注入进去 ,而后bean缓冲起来 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //原型和单例没有太大的区别,主要是是否缓冲区实例,原型每次都建立新的实例 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } --------代码省略 具体可去看spring源码----- return (T) bean; }
基本大概从beanFactory获取bean 就是这个过程。
类图
从ApplicationContext和BeanFactory类图中能够看出它们的顶级接口大部分是相同的,只是ApplicationContext接口更多一些。ApplicationContext的实现类实际上是包装了DefaultListableBeanFactory类着一点能够从其代码能够看出
全部的有关bean的获取等操做都会委托到DefaultListableBeanFactory
ApplicationContext多了MessageSource,ApplicationEventPulisher,ResourceLoader等接口。
这里篇幅比较长了,不在详细介绍ApplicationContext接口。
IOC 容器 对bean的主要操做就是这样。