Spring框架之beans源码完全解析
导读:Spring可以说是Java企业开发里最重要的技术。而Spring两大核心IOC(Inversion of Control控制反转)和AOP(Aspect Oriented Programming面向切面编程)其中又以IOC最为核心。IOC容器是Spring的核心模块,Spring提供了两种类型的容器,一个是BeanFactory,一个是ApplicationContext,而ApplicationContext是BeanFactory扩展来的。
本文就Spring框架的beans源码进行解析,主要从以下几个方面进行:一是Spring框架介绍,对Spring整体架构有个直观的了解;二是对beans源码文件清单进行梳理,共12大类,257个java文件,对DefaultListableBeanFactory等一些核心类进行了重点分析;三是对BeanDefinition进行解析,BeanDefinition 在 spring 中贯穿始终,是spring 一块基石;四是对Bean默认标签解析全过程进行了分析;五是以doGetBean函数为核心,分析Bean的加载过程;六是介绍ApplicationContext和BeanFactory两种容器的Bean的生命周期。
文章目录
一、Spring框架简介
二、Beans源码文件清单
1、 org.springframework.beans包含的类和接口
2、 org.springframework.beans.annotation包含的类和接口
3、 org.springframework.beans.propertyeditors包含的类和接口
4、 org.springframework.beans.support包含的类和接口
5、 org.springframework.beans.factory包含的类和接口
6、 org.springframework.beans.factory.annotation包含的类和接口
7、 org.springframework.beans.factory.config包含的类和接口
8、 org.springframework.beans.factory.parsing包含的类和接口
9、 org.springframework.beans.factory.serviceloader包含的类和接口
10、org.springframework.beans.factory.support包含的类和接口
11、org.springframework.beans.factory.wiring包含的类和接口
12、org.springframework.beans.factory.xml包含的类和接口
三、BeanDefinition解析
(一)BeanDefinition是什么
(二)BeanDefinition属性
(三)BeanDefinition实现类
(四)BeanDefinition的载入和解析
四、Bean默认标签解析
(一)默认标签
(二)bean标签的解析及注册
(三)解析BeanDefinition
(四)创建用于承载属性的GenericBeanDefinition
(五)解析各种属性
五、Bean的加载
(1)转换对应的beanName
(2)尝试从缓存中加载单例
(3)bean的实例化
(4)原型模式(prototype)的依赖检查
(5)检测parentBeanFactory
(6)GenericBeanDefinition转为RootBeanDefinition
(7)寻找依赖
(8)依据scope创建bean
(9)类型转换
六、Bean的生命周期
(1)ApplicationContext Bean生命周期
(2)BeanFactory Bean生命周期
一、Spring框架简介
Spring框架是一个Java平台,用来提供全面的基础设施支持开发Java应用程序, Spring负责处理基础设施部分,这样你就可以专注于应用程序部分。Spring框架内,把一级对象通过设计模式封装起来,这样你就可以集成到自己的应用程序中而不用关注他们是如何在后台工作的。
目前,Spring框架按照功能组织成大约20个模块。这些模块分为核心容器、数据访问/集成、Web、AOP(面向切面的编程)、instrument(支持和类加载器的实现来在特定的应用服务器上使用)、消息和测试,如下图所示。
从上面可以看出Spring主要分成六个模块:
1.Spring核心容器:核心容器是Spring框架的重要组成部分,也可以说是Spring框架的基础。他在整个框架中的作用是负责管理对象的创建,管理,配置等操作。其主要包含spring-core、spring-beans、spring-context、spring-expression组件。
2.面向切面编程:Spring框架还提供了面向切面编程的能力,利用面向切面编程,可以实现一些面向对象编程无法很好实现的操作。例如,将日志,事务与具体的业务逻辑解耦。其主要包含spring-aop、spring-aspects组件。
3.Instrumentation:该模块提供了为JVM添加代理的功能,该模块包含spring-instrument、spring-instrument-tomcat组件,使用较少,不必过分关注。
4.数据访问与集成:Spring框架为了简化数据访问的操作,包装了很多关于数据访问的操作,提供了相应的模板。同时还提供了使用ORM框架的能力,可以与很多流行的ORM框架进行整合,如hibernate,mybatis等等的著名框架。还实现了数据事务的能力,能够支持事务。包含spring-jdbc、spring-tx、spring-orm、spring-oxm、spring-jms、spring-messaging组件。
5.Web和远程调用:Spring框架支持Web开发,以及与其他应用远程交互调用的方案。包含spring-web、spring-webmvc、spring-websocket、spring-webmvc-portlet组件。
6.Spring测试:Spring框架提供了测试的模块,可以实现单元测试,集成测试等等的测试流程,整合了JUnit或者TestNG测试框架。包含spring-test组件。
我们为什么要使用Spring框架?简单来说,使用Spring框架可以带来以下好处:
1、轻量:非入侵性的、所依赖的东西少、资源占用少、部署简单,不同功能选择不同的 jar 组合。
2、容器:工厂模式实现对 JavaBean 进行管理,通过控制反转(IOC)将应用程序的配置和依赖性与应用代码分开。
3、松耦合:通过 xml 配置或注解即可完成 bean 的依赖注入。
4、AOP:通过 xml 配置 或注解即可加入面向切面编程的能力,完成切面功能,如日志,事务等的统一处理。
5、方便集成:通过配置和简单的对象注入即可集成其他框架,如 Mybatis、Hibernate。
6、丰富的功能:JDBC层抽象、事务管理、MVC、Java Mail、任务调度、JMX、JMS、JNDI、EJB、动态语言、远程访问、Web Service等。
其中,最核心的就是上述的2和4:IOC(控制反转)和AOP(面向切面编程)。
IOC:在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成。在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,而这样就会使得对象间的耦合度高了。比如A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起。而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好,A对象不需要关心这些细节问题,A得到Spring给之后,两个对象一起协作完成要完成的工作即可。
所以控制反转是将创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IOC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IOC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IOC容器了,通过IOC容器来建立它们之间的关系。
AOP可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
同OOP技术恰恰相反,AOP利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
二、Beans源码文件清单
spring项目源码由多个子项目组成,如spring-beans,spring-context,spring-core,spring-aop,spring-web,spring-webmvc等,整个项目结构如下图:
其中spring beans有如下的源文件包:
1、org.springframework.beans:包含了操作java bean的接口和类。
2、org.springframework.beans.annotation:支持包,提供对java 5注解处理bean样式的支持。
3、org.springframework.beans.propertyeditors:属性编辑器,用来将string类型的值转换为object类型。
4、org.springframework.beans.support:org.springframework.beans的支持包,比如一组bean的排序和保持工具类等。
5、org.springframework.beans.factory:实现spring轻量级IOC容器的核心包。
6、org.springframework.beans.factory.annotation:配置基于注解驱动的bean的支持包。
7、org.springframework.beans.factory.config:bean工厂的SPI接口和配置相关的处理类。
8、org.springframework.beans.factory.parsing:bean definition解析的支持基础类。
9、org.springframework.beans.factory.serviceloader:jdk1.6 ServiceLoader基础类的支持包。
10、org.springframework.beans.factory.support:org.springframework.beans.factory 包的支持类。
11、org.springframework.beans.factory.wiring:一种决定一个bean实例的元数据的机制。
12、org.springframework.beans.factory.xml:包含了一个基于xml的beanFactory实现,也包含一个标准的spring-beans的dtd。
在介绍beans的类和接口之前,先理清下bean的概念,在 Spring 中,构成应用程序主干并由Spring IOC容器管理的对象称为bean。bean是一个由Spring IOC容器实例化、组装和管理的对象。简而言之,bean是对象,而且由Spring中IOC容器进行管理,我们的应用程序由一个个bean构成。
1、org.springframework.beans包含的类和接口
1.1 BeanInfoFactory:创建java.beans.BeanInfo实例的策略,定义了方法BeanInfo getBeanInfo()。
1.2 ExtendedBeanInfo:BeanInfo接口的实现类,BeanInfo接口是在java.beans包中的。
1.3 ExtendedBeanInfoFactory:BeanInfoFactory接口的实现,用来评估bean的class是否有不满足JavaBean规范的set方法,因而是否满足Spring ExtendedBeanInfo作为内省的候选。
1.4 BeanWrapper:Spring底层JavaBean公共基础的核心接口。通常不直接使用,而是通过BeanFactory间接使用。作用:提供对标准javabean的分析和操作方法:单个或者批量获取和设置属性值,获取属性描述符,查询属性的可读性和可写性等。支持属性的嵌套设置,深度没有限制。
1.5 CachedIntrospectionResults:内部类。在BeanWrapperImpl类中会用到,为这个类的javabean缓存属性描述信息,以提高效率,减小开销。
1.6 BeanWrapperImpl:BeanWrapper的默认实现。可以根据需求,将集合与数组的值转换到对应目标对象的集合和数组。自定义的属性编辑器通过属性编辑器的setValue,setAsText方法实现上述的转换功能。
1.7 Mergeable:代表一个对象的值可以和父对象的值进行合并的接口。其主要的子类有:ManagedList、ManagedArray、ManagedMap、ManagedProperties、ManagedSet。这几个类在org.springframework.beans.factory 包中。
1.8 BeanMetadataElement:传送配置源对象的超级接口。定义了唯一的方法:Object getSource(),其子类和子接口如下图:
1.9 BeanMetadataAttribute:bean definition定义中的属性-键值对(key-value)容器。
1.10 BeanMetadataAttributeAccessor:AttributeAccessorSupport的拓展,为了追踪对象定义源。
1.11 GenericTypeAwarePropertyDescriptor:JavaBeans的PropertyDescriptor类的拓展,重载了getPropertyType函数。
1.12 PropertyDescriptorUtils:抽象类,PropertyDescriptor内部使用。PropertyDescriptor(属性描述器)在软件包 java.beans中,用来表示JavaBean 通过存储器方法导出的一个属性。
1.13 PropertyMatches:根据一个可配置的距离计算一个属性的匹配度。可同时用于java bean的成员变量(fields)与属性(properties)。其核心函数calculateStringDistance,利用Levenshtein算法计算两个字符串的相似度。另解析下Java中成员变量(Fields)和属性(Properties)的区别: 成员变量Fields就是定义的字段。根据SUN官方定义,属性是指get或者set方法名去掉get或者set后,把剩余的部分首字母改为小写后,即为这个类的属性。
1.14 PropertyAccessor:获取和设置属性(例如对象bean的属性,对象的Field)的通用接口,它用来作为BeanWrapper的基础接口。其继承关系如下图:
1.15 AbstractPropertyAccessor:PropertyAccessor接口的抽象实现。
1.16 AbstractNestablePropertyAccessor:继承自AbstractPropertyAccessor,也是ConfigurablePropertyAccessor的一种,可以为典型的一些应用场景提供支持。
1.17 ConfigurablePropertyAccessor:PropertyAccessor配置方法的封装接口。是BeanWrapper的父接口。
1.18 DirectFieldAccessor:ConfigurablePropertyAccessor接口的实现类,用来直接获取实例的字段(f ield)。
1.19 PropertyAccessorFactory:获取PropertyAccessor实例简单工厂,特别是BeanWrapper实例(BeanWrapper继承自PropertyAccessor)。
1.20 PropertyAccessorUtils:PropertyAccessor类获取和设置属性的一些工具方法。
1.21 PropertyEditorRegistrar:用一个属性编辑器注册器(PropertyEditorRegistry)注册一个自定义的属性编辑器(PropertyEditor)的策略接口。
1.22 PropertyEditorRegistry:属性编辑器注册器。封装了JavaBean属性编辑器的注册方法。主要函数为void registerCustomEditor()。
1.23 PropertyEditorRegistrySupport:PropertyEditorRegistry接口的基本实现类。主要作为BeanWrapperImpl父类使用。
1.24 PropertyValue:一个对象,用来保存一个bean单独属性值信息。用对象来保存PropertyValue(name, value)信息,相对于map保存可以提供更大的灵活性。
1.25 PropertyValues:包含了一个或者多个PropertyValue对象,通常用作特定的一个目的bean的属性更新。
1.26 MutablePropertyValues:PropertyValues接口的默认实现,提供了对属性的一些简单操作,比如get、add、set、merge、remove方法等。
1.27 PropertyValuesEditor:PropertyValues 对象的编辑器。
1.28 TypeConverter:定义了类型转换方法的接口。将值转换成指定的类型。
1.29 TypeConverterDelegate:内部用的类,用来将属性值转换为目标类型的值。
1.30 SimpleTypeConverter:TypeConverter接口的简单实现,它不会针对一个特定的目标进行操作。
1.31 TypeConverterSupport:TypeConverter接口的基本实现类,使用了代理typeConverterDelegate。这个类主要用作BeanWrapperImpl的基类使用。
1.32 BeanUtils:JavaBeans的静态工具方法,用来初始化bean,检查bean属性类型,复制bean属性等。
1.33 BeansException:在beans包和子包中所抛出的所有异常的抽象超类。
1.34 BeanInstantiationException:bean初始化失败时抛出的异常。
1.35 FatalBeanException:在bean包和子包中遇到的不可恢复问题抛出的异常,例如:当引用一个无效的bean属性时抛出的InvalidPropertyException异常。
1.36 ConversionNotSupportedException:当一个bean的属性没有适合的编辑器或者转换器时所抛出的异常。
1.37 MethodInvocationException:当一个bean属性的get和set方法抛出异常时抛出该异常,类似于InvocationTargetException。
1.38 NullValueInNestedPathException:当获取一个内嵌属性路径的属性时遇到空指针异常时抛出的异常。
1.39 TypeMismatchException:当试图设置bean属性时抛出的类型不匹配异常。
1.40 InvalidPropertyException:遇到非法的bean property时异常类。
1.41 NotReadablePropertyException:当试图获取一个不可读属性的属性值时抛出的异常,典型场景bean属性没有get方法。
1.42 NotWritablePropertyException:当试图向一个不可写属性写入属性值时抛出的异常,典型场景bean属性没有set方法。.
1.43 PropertyAccessException:获取属性相关的异常超类,例如类型不匹配或者目标调用异常。
1.44 PropertyBatchUpdateException组合异常,由多个的单个PropertyAccessException实例组成。
2、org.springframework.beans.annotation包含的接口和类
2.1 AnnotationBeanUtils:JavaBean类型注解的通用工具方法。定义了一个静态方法:public static void copyPropertiesToBean(),将指定Annotation的属性复制到目标bean中。如果属性在excludeProperties中定义了,那么就不会被复制。
3、org.springframework.beans.propertyeditors包含的接口和类
属性编辑器,用来将string类型的值转换成object类型的。他们都继承自PropertyEditorSupport,这个类可以用于自定义的类型转换,继承后重写了public void setAsText(),public String getAsText() 两个方法。注意PropertyEditor和PropertyEditorSupport都是java自己定义的,不是Spring的。包含的类有:
3.1 ByteArrayPropertyEditor
3.2 CharacterEditor
3.3 CharArrayPropertyEditor
3.4 CharArrayPropertyEditor
3.5 ClassArrayEditor
3.6 ClassEditor
3.7 CurrencyEditor
3.8 CustomBooleanEditor
3.9 CustomCollectionEditor
3.10 CustomDateEditor
3.11 CustomMapEditor
3.12 CustomNumberEditor
3.13 FileEditor
3.14 InputSourceEditor
3.15 InputStreamEditor
3.16 LocaleEditor
3.17 PathEditor
3.18 PatternEditor
3.19 PropertiesEditor
3.20 ReaderEditor
3.21 ResourceBundleEditor
3.22 StringArrayPropertyEditor
3.23 StringTrimmerEditor
3.24 StringTrimmerEditor
3.25 URIEditor
3.25 URLEditor
3.27 UUIDEditor
3.28 ZoneIdEditor
4、org.springframework.beans.support包含的接口和类
4.1 ArgumentConvertingMethodInvoker:MethodInvoker的子类,通过TypeConverter将真实目标方法的指定参数进行转换。
4.2 MutableSortDefinition:SortDefinition接口的可变实现。支持在对同一个属性值进行设置的时候可以利用升序排列的值进行切换。
4.3 PagedListHolder:PagedListHolder是一个简单的状态保持,它处理一组对象,将它们分页。分页的起始页从0开始。主要用在web网站的用户界面上。
4.4 PropertyComparator:对两个bean进行比较,通过BeanWrapper来比较指定bean的属性。
4.5 ResourceEditorRegistrar:继承了PropertyEditorRegistrar,使用资源编辑器来填充指定的PropertyEditorRegistry。
4.6 SortDefinition:根据一个指定的属性对一组bean实例进行排序的定义类。isAscending为True时进行升序排列,为False进行降序排列。
5、org.springframework.beans.factory包含的接口和类
5.1 Aware:它是一个标签,内部没有任何属性或者方法。它是一个超级接口,实现它的子接口的bean标志着在spring容器中可以被特定框架的对象通知到,通过回调方式的方法来完成这种通知。继承关系如下图:
5.2 BeanClassLoaderAware:允许一个获取它的classLoader(即当前bean factory加载bean类使用的class loader)的回调类,实现了void setBeanClassLoader(ClassLoader classLoader)。
5.3 BeanFactoryAware:实现此接口的bean可以获取到它们自己的Beanfactory。比如,bean可以通过factory寻找一些具有协作关系的beans。
5.4 BeanNameAware:实现此接口的bean可以在一个bean factory中获取到它们的bean名称。但是需要注意的是,并不推荐一个通过一个bean name去定位bean,在外部配置中,这种对应关系并不严格对应。
5.5 NamedBean:对应BeanNameAware接口,返回bean的名称。函数String getBeanName()。
5.6 BeanFactory:获取spring bean容器的根接口。其主要函数有getBean()、getBeanProvider()、containsBean()、isSingleton()、isPrototype()、isTypeMatch()、getType()、getAliases()。其继承关系如下图:
5.7 BeanFactoryUtils:beanFactory上的操作方法工具类,特别是在ListableBeanFactory接口上。包括返回bean的个数,bean的名字,bean实例等,考虑到了一些具有嵌套关系的hierarchy factory,而如果这些方法在ListableBeanFactory中不需要考虑这些。
5.8 HierarchicalBeanFactory:子接口,实现此接口的bean factory具有层次结构即可以获取父BeanFactory。方法 getParentBeanFactory()获取父BeanFactory;方法containsLocalBean()判断本地bean factory是否含有指定名字的bean,不考虑在父BeanFactory中的情况。
5.9 ListableBeanFactory:beanFactory接口的实现,实现此接口的beanFactory能遍历他们内部的所有bean实例,而不用根据客户请求通过名字一个一个的去搜索bean。提供的函数如下:
containsBeanDefinition();判断factory是否包含指定命名的bean definition;
getBeanDefinitionCount();返回在factory中定义的bean的个数;
getBeanDefinitionNames();返回该factory中定义的所有bean的名字;
getBeanNamesForType();返回指定类型的bean的名字;
getBeansOfType();返回指定类型的bean实例;
getBeanNamesForAnnotation(); 返回被指定的标签标注的所有bean的名字;
getBeansWithAnnotation();返回被指定标签标注的所有bean实例。
5.10 FactoryBean:实现了此接口的bean不能看做一个通常意义上的bean,一个FactoryBean虽然以bean的形式来定义,但它暴露的对象(getObject())通常是它创建的对象,而不是作为一个bean实例暴露自己。
5.11 SmartFactoryBean:FactoryBean接口的扩展实现。实现该接口可以表明每次是否返回的都是独立的实例,因为用isSingleton()函数判断为假,表明非单例模式,但这并不足以表明返回的都是独立的实例。
5.12 ObjectFactory:一个对象工厂,当触发时会返回所有对象的实例(可以是共享的或者独立的)。
5.13 ObjectProvider:继承自ObjectFactory,ObjectFactory的一个变种,专门用来为注入点服务。
5.14 InjectionPoint:注入点的简单描述,指向一个方法或者构造函数的参数或者成员变量(field)。
5.15 InitializingBean:实现此接口的bean在BeanFactory设置为它们的属性时只需要执行一次,例如:初始化定制或者仅仅检查必须存在的属性是否已经设置完成等等。
5.16 SmartInitializingSingleton:回调接口,当一个bean工厂创建时,单例singleton实例化阶段结束时被触发。一些单例模式的bean可以实现此接口,在单例实例做完一些规律性、常做的初始化可以用来做一些初始化工作。以避免突发的Early initialization产生的负面效果。比如ListableBeanFactory中的getBeansOfType函数调用。注:对于单件的初始化有(Lazy Initialization)和(Early initialization)两种方法。
5.17 BeanCreationException:beanfactory在试图通过bean definition创建一个bean时遇到错误而抛出的异常。
5.18 BeanCreationNotAllowedException:若当前不允许创建一个bean时(例如在beanFactory关闭过程中)而试图去获取bean的请求时抛出的异常。
5.19 BeanCurrentlyInCreationException:一个bean的引用当前正在创建过程中抛出的异常。
5.20 BeanDefinitionStoreException:beanFactory遇到一个无效的bean definition抛出的异常 。
5.21 BeanExpressionException:获取一个表达式的值失败时抛出的异常。
5.22 BeanInitializationException:bean初始化异常时抛出。
5.23 BeanIsAbstractException:当试图获取一个定义为abstract的bean definition时抛出的异常。
5.24 BeanIsNotAFactoryException:当一个bean不是工厂,但用户试图通过给定bean名称访问工厂。
5.25 BeanNotOfRequiredTypeException:当一个bean的类型和期望类型不匹配时抛出的异常。
5.26 CannotLoadBeanClassException:BeanFactory不能加载指定bean的class类时抛出的异常。
5.27 FactoryBeanNotInitializedException:工厂bean没有初始化异常。
5.28 NoSuchBeanDefinitionException:没有该bean definition异常。
5.29 NoUniqueBeanDefinitionException:返回多个bean definition异常。
5.30 UnsatisfiedDependencyException:当有依赖检查时,在bean factory定义中,bean的依赖或者属性没有指定时抛出的异常。
6、org.springframework.beans.factory.annotation包含的接口和类
6.1 AnnotatedBeanDefinition:BeanDefinition接口的扩展,BeanDefinition在org.springframework. beans.factory.config包中。
它暴露了它的bean 类的AnnotationMetadata,不需要加载类。提供了一个getMetadata()方法来获取该bean definition的注解元数据, ClassMetadata定义了一个特定类的抽象元数据,不需要加载此类即可访问,主要方法有:
1)String getClassName()返回该类的名称。
2)boolean isInterface()返回该类是否是接口。
3)boolean isAbstract()返回该类是否为抽象类。
4)boolean isConcrete()返回该类是否为具体类。
5)boolean isFinal()返回该类是否为final类。
6)boolean hasSuperClass()返回该类是否有父类。
7)String getSuperClassName()返回父类的名称,没有的话返回null。
8)String[] getInterfaceNames()返回继承的接口数组,如果没有,返回空。
9)String[] getMemberClassNames()返回引用的类的名称。
6.2 AnnotatedGenericBeanDefinition:继承自GernericBeanDefinition和AnnotatedBeanDefinition,通过暴露AnnotatedBeanDefinition接口来增加对注解元数据的支持。GernericBeanDefinition在org.springframework.beans.factory.support包中,是一站式的标准bean Definition。
Spring自带依赖注入注解:
1 @Required:依赖检查;
2 @Autowired:按类型自动装配,用于替代基于XML配置的自动装配。基于@Autowired的自动装配,默认是根据类型注入,可以用于构造器、字段、方法注入
3 @Value:注入int、float、String等基本数据类型,只能标注在成员变量、setter方法上。
4 @Qualifier:限定描述符,用于细粒度选择候选者。@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者。@Qualifier(value = "限定标识符")
6.3 Required:public @interface Required 依赖检查。
6.4 Autowired:public @interface Autowired:可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。
6.5 Value:public @interface Value:用于注入SpEL表达式,可以放置在字段方法或参数上。
6.6 Qualifier:@Qualifier(value = "限定标识符") 。对应于基于XML配置中的标签,@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者@Qualifier(value = "限定标识符") 。
6.7 Configurable:@Configurable 注解中的autowire属性就可以让Spring来自动装配。
6.8 RequiredAnnotationBeanPostProcessor(@required注解实现类):实现了BeanPostProcessor,对配置了Required注解的javaBean属性进行强制检查。
6.9 AutowiredAnnotationBeanPostProcessor (Autowired注解实现类):实现了BeanPostProcessor接口,它自动绑定注解的field,setter方法和任意配置方法。AutowiredAnnotationBeanPostProcessor 间接继承了BeanPostProcessor,它自动绑定注解的field,setter方法和任意的配置方法。当检测到5个java注解时这些成员被注入其中。spring默认的注解为@Autowired和@Value。另外:也支持JSR-330的@inject注解,作为@Autowired的替代方案。
6.10 AnnotationBeanWiringInfoResolver(@configurable注解实现):继承自BeanWiringInfoResolver,使用configurable的注解来查找哪些类需要自动绑定。设置 @Configurable 注解中的autowire属性就可以让Spring来自动装配:@Configurable(autowire= Autowire.BY_TYPE) 或者 @Configurable(autowire=Autowire.BY_NAME,这样就可以按类型或者按名字自动装配了。
6.11 QualifierAnnotationAutowireCandidateResolver(@qualifier的注解实现类):间接实现了AutowireCandidateResolver,对要自动绑定的field或者参数和bean definition根据@qualifier注解进行匹配。同时也支持通过@value注解来绑定表达式的值。AutowireCandidateResolver是一个策略接口,由它来决定特定的bean definition对特定的依赖是否可以作为一个自动绑定的候选项。
6.12 InitDestroyAnnotationBeanPostProcessor(初始化和销毁方法的注解实现类):间接继承了BeanPostProcessor,实现了通过注解来初始化init和销毁destroy方法。是spring的InitializingBean和DisposableBean回调接口的注解实现。
6.13 BeanFactoryAnnotationUtils:关联注解的bean的查询的工具方法,例如spring的@Qualifier注解。
6.14 CustomAutowireConfigurer:继承了BeanFactoryPostProcessor,它使自定义的自动绑定qualifier类型的注册更便利。.
6.15 InjectionMetadata:管理注入元数据的内部类。
6.16 Lookup:@Lookup的注解,这是一个作用在方法上的注解,被其标注的方法会被重写,然后根据其返回值的类型,容器调用BeanFactory的getBean()方法来返回一个bean。
比如:如果有一个类C,需要用到类B,如果使用@Autowired注解注入B,那么B每次调用都是同一个对象,即使B不是单例的,现在我希望每次调用B都是不一样的,那么实现方案有2个:方案A : 每次从容器中获取B;方案B: 使用@lookup注解。
6.17 ParameterResolutionDelegate:代理类,用来解析外部构造函数或方法上的自动装配的参数。
6.18 Autowire:决定自动绑定状态的枚举,即一个bean的依赖是否由spring容器使用setter方式自动注入。这个是spring DI的核心概念。
7、org.springframework.beans.factory.config包含的接口和类
FactoryBean和BeanFactory区别:
FactoryBean:Spring 中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean 即 FactoryBean。FactoryBean跟普通Bean不同,其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象。创建出来的对象是否属于单例由isSingleton中的返回决定。Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。
BeanFactory:以Factory结尾,表示它是一个工厂类(接口), 是负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等。
7.1 AbstractFactoryBean:实现了FactoryBean的简单模板超类,它根据singleton标志来决定是创建一个单例还是一个prototype对象。
7.2 ListFactoryBean:共享一组(list)实例的简单工厂bean。
7.3 MapFactoryBean:共享一组(map)实例的简单工厂bean。
7.4 SetFactoryBean:共享set实例的简单工厂bean。
7.5 MethodInvokingFactoryBean:一个有返回值的工厂bean,它返回触发一个静态或者实例的方法的结果。
7.6 MethodInvokingBean:一个简单的method invoker bean,和MethodInvokingFactoryBean不同,它并不返回触发一个方法的结果,而是仅仅返回触发一个目标方法。
7.7 FieldRetrievingFactoryBean:检索静态或者非静态Field的值的工厂bean。
7.8 PropertyPathFactoryBean:通过给定目标对象计算属性路径的工厂bean。
7.9 ObjectFactoryCreatingFactoryBean:一个有返回值的工厂bean,它返回ObjectFactory。
7.10 ProviderCreatingFactoryBean:返回一个JSR-330 Provider的工厂bean,JSR-330 Provider反过来从beanFactory返回一个bean资源。JSR-330 是 Java 的依赖注入标准。
7.11 ServiceLocatorFactoryBean:继承自FactoryBean,在beanFactory中创建一个动态代理,来代理一个具有一个或者多个服务或者类型的接口。
7.12 PropertiesFactoryBean:它支持从classpath位置的文件中读取属性实例的工厂bean。
7.13 YamlMapFactoryBean:为读取YAML源文件的Map的工厂,保持YAML声明的值类型和结构的原样。
7.14 YamlProcessor:YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便。它实质上是一种通用的数据串行化格式。该类作为YAML factories基类。
7.15 YamlPropertiesFactoryBean:从YAML源文件中读取属性的工厂,用来暴露字符串属性值扁平型组织结构。
7.16 AutowireCapableBeanFactory:beanFactory的扩展接口,实现了自动绑定功能。这个接口的两个主要方法是:autowire:使用给定的自动绑定策略,来给一个类的新实例进行初始化。autowireBeanProperties使用名称或者类型来自动绑定给定bean实例的属性。
7.17 ConfigurableBeanFactory:将会被大部分beanFactory实现的配置接口。为对bean factory进行配置提供一些功能服务,包括BeanFactory接口中的一些函数。这个接口并不用于普通的应用代码,而是用于同BeanFactory或 ListableBeanFactory一起出现使用。
7.18 ConfigurableListableBeanFactory:将会被大部分ListablebeanFactory实现的配置接口。除了ConfigurableBeanFactory,该接口也提供分析和修改bean definitions的功能函数,也能预实例化单例对象。
7.19 BeanDefinition:一个bean实例的描述,它含有属性值、构造参数值。它的实现子类还提供更多的信息。bean的定义BeanDefinition,包装BeanWrapper是java bean的基础。可以这么说,是spring的基石,再怎么强调它的重要性都不为过。
BeanDefinition 作用:一个BeanDefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。BeanDefinition仅仅是一个最简单的接口,主要功能是允许BeanFactoryPostProcessor,例如PropertyPlaceHolderConfigure(PropertyPlaceholderConfigurer是BeanFactoryPostProcessor的一个重要实现)能够检索并修改属性值和别的bean的元数据。
BeanDefinition的继承关系:(1)父接口:AttributeAccessor、BeanMetadataElement。其中,AttributeAccessor接口定义了最基本的对任意对象的元数据的修改或者获取,BeanMetadataElement接口提供了一个getResource()方法,用来传输一个可配置的源对象。(2)子接口:AnnotatedBeanDefinition。(3)子类: AbstractBeanDefinition、AnnotatedGenericBeanDefinition、ChildBeanDefinition、GenericBeanDefinition、RootBeanDefinition、ScannedGenericBeanDefinition。
7.20 BeanDefinitionCustomizer:定制一个给定的bean definition的回调函数,用在Lambda 表达式或者方法引用中。
7.21 BeanDefinitionHolder:使用名称或者别名来保存BeanDefinition。可以为内部bean作为占位符注册。
7.22 BeanDefinitionVisitor:遍历BeanDefinition对象的参观者类,特别是也遍历bean中的属性值和构造参数值,解析bean的元数据值。在PlaceholderConfigurerSupport中被使用,用来解析包含在BeanDefinition中所有的字符串值,解析发现的所有占位符。
7.23 BeanPostProcessor:允许对一个新的bean实例进行定制修改的工厂钩子。
7.24 BeanFactoryPostProcessor:允许对一个applicationContext中的bean definition进行定制修改的工厂钩子,修改context内含的bean factory中bean的属性值。
7.25 DestructionAwareBeanPostProcessor:BeanPostProcessor的子接口,它增加了一个销毁前回调方法。
7.26 InstantiationAwareBeanPostProcessor:BeanPostProcessor的子接口,它增加了一个初始化前回调方法,还有一个在初始化后但显式设置属性或者自动绑定发生前的回调方法。
7.27 InstantiationAwareBeanPostProcessorAdapter:实现了SmartInstantiationAwareBeanPostProcessor所有方法的适配器,它没有任何操作,不会改变容器对bean进行初始化的处理过程。
7.28 SmartInstantiationAwareBeanPostProcessor:InstantiationAwareBeanPostProcessor的扩展接口,它增加了对一个处理过bean的最终类型进行预测的回调方法。
7.29 CustomEditorConfigurer:继承自BeanFactoryPostProcessor,给自定义属性编辑器的注册提供了便利的方法。
7.30 CustomScopeConfigurer:BeanFactoryPostProcessor的简单实现,给自定义Scope的注册提供了便利的方法,上面提到ConfigurableBeanFactory提供了Scope的注册。
7.31 PreferencesPlaceholderConfigurer:PropertyPlaceholderConfigurer的子类,支持JDK1.4中的Preferences API (java.util.prefs)
7.32 PropertyOverrideConfigurer:属性资源配置器,它支持在applicationContext中重写一个bean的属性值。
7.33 PropertyPlaceholderConfigurer:PlaceholderConfigurerSupport的子类,它解析本地属性或者系统属性或者环境变量定义的占位符(以${}描述)。
7.34 PropertyResourceConfigurer:支持从一个属性资源中对单个bean的属性值进行配置。
7.35 BeanExpressionContext:计算一个BeanDefinition内部的表达式的容器对象。
7.36 BeanExpressionResolver:通过计算一个表达式来解析为值的策略接口。
7.37 EmbeddedValueResolver:StringValueResolver适配器,用于解析ConfigurableBeanFactory占位符和表达式。
7.38 BeanReference:暴露bean名称的引用接口。这个接口并不需要实际指向一个bean实例,只需要逻辑指向bean的名字。
7.39 RuntimeBeanNameReference:固定占位符类,当在beanfactory中作为另外一个bean名称的引用时,作为属性值对象,将在运行时进行解析。
7.40 RuntimeBeanReference:固定占位符类,当在beanfactory中作为另外一个bean的引用时,作为属性值对象,将在运行时进行解析。
7.41 TypedStringValue:保存一个类型的属性值。
7.42 ConstructorArgumentValues:保存构造方法的参数值,特别是作为Beandefinition的一部分。
7.43 DependencyDescriptor:将要注入的特定依赖的描述。
7.44 DeprecatedBeanWarner:继承自BeanFactoryPostProcessor,记录@Deprecated bean的报警信息。
7.45 PlaceholderConfigurerSupport:属性资源配置器的抽象基类,它解析BeanDefinition中属性值的占位符。
7.46 AutowiredPropertyMarker:简单的标记类,用于自动装载属性值,增加到BeanDefinition的getPropertyValues()函数为一个指定的bean 属性。
7.47 NamedBeanHolder:给定名字的bean实例的简单占位符。
7.48 SingletonBeanRegistry:定义了共享bean实例的注册接口。
7.49 Scope:ConfigurableBeanFactory使用的策略接口,代表了bean实例所在的作用域。Bean的作用域就是指Bean实例的生存空间或者有效范围。scope=[singleton, prototype, request, session, global session]
1、singleton(单实例):在每个Spring IOC容器中,一个Bean定义对应一个对象实例。这是Spring容器默认的作用域。当一个Bean的作用域为Singleton时,Spring IOC容器中只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean定义相匹配,就只会返回Bean的同一个实例。这个单一实例会被存储到单例缓存(Singleton Cache)中,并且所有针对该Bean的后续请求和引用都将返回被缓存的对象实例。单实例模式对于无会话状态的Bean(DAO组件、业务逻辑组件)来说是理想的选择。
2、prototype(原型模式):一个bean定义对应多个对象实例。prototype作用域的Bean在每次对该Bean请求时都会创建一个新的Bean实例,对需要保持会话状态的Bean(Struts2中充当控制器的Action类)应该使用prototype作用域。spring不能对一个原型模式Bean的整个生命周期负责,容器在初始化、装配好一个原型模式实例后,将它交给客户端,就不再过问了。因此,客户端要负责原型模式实例的生命周期管理。
3、request:在一次Http请求中,容器会返回该Bean的同一个实例,而对于不同的用户请求,会返回不同的实例。该作用域仅在基于Web的Spring ApplicationContext情形下有效。
4、session:在一次HttpSession中,容器会返回该Bean的同一个实例。而对于不同的HttpSession请求,会返回不同的实例。该作用域仅在基于Web的Spring ApplicationContext情形下有效。
5、global session:在全局的HTTPSession中,容器会返回该Bean的同一个实例。仅在使用portlet context时有效。
8、org.springframework.beans.factory.parsing包含的接口和类
8.1 AbstractComponentDefinition:ComponentDefinition接口的基本实现,提供了getDescription()来代理ComponentDefinition.getName()方法。
8.2 BeanComponentDefinition:基于一个标准BeanDefinition的ComponentDefinition,暴露指定bean的指定beanDefinition,内部BeanDefinition和BeanReference。
8.3 ComponentDefinition:描述在同一配置的Context中一组BeanDefinition和BeanReference的逻辑视图的接口。
8.4 CompositeComponentDefinition:保存了一个或者多个内嵌ComponentDefinition实例的ComponentDefinition实现,它把这些ComponentDefinition实例聚合成具有命名的组。
8.5 AliasDefinition:代表在解析进程中一个别名已经被注册。
8.6 ImportDefinition:在解析进程中,代表一个import已经被处理。
8.7 DefaultsDefinition:一个默认definition标识接口,继承了BeanMetadataElement,没有实现任何方法。
8.8 ConstructorArgumentEntry:代表了构造参数。
8.9 BeanEntry:代表了一个BeanDefinition。
8.10 PropertyEntry:代表了一个javaBean的属性。
8.11 QualifierEntry:代表了一个自动绑定的备选qualifier。
8.12 EmptyReaderEventListener:ReaderEventListener接口的空实现,所有回调方法都没有提供可执行操作。
8.13 ReaderEventListener:接受在读取BeanDefinition进程中注册组件、别名、import时的回调接口。
8.14 FailFastProblemReporter:ProblemReporter接口的简单实现,当遇到错误发生时展示fail-fast行为。
8.15 ProblemReporter:SPI接口,支持tool或者外部进程处理在beanDefinition解析期间报出的错误或者异常。
8.16 PassThroughSourceExtractor:SourceExtractor的简单实现,它通过一个attachment来传递备选的源数据类型对象。
8.17 NullSourceExtractor:SourceExtractor接口的简单实现,返回null作为source元数据。
8.18 SourceExtractor:简单策略接口,允许工具控制source元数据关联到bean definition元数据。
8.19 Location:模型接口,一个资源位置的模型。
8.20 ParseState:在解析进程中作为一个简单的基于栈结构的追踪逻辑位置类。
8.21 Problem:代表了一个beanDefinition配置问题。
8.22 ReaderContext:bean definition读取进程中传递的一个Context,封装了所有相关的配置,包括状态。
8.23 BeanDefinitionParsingException:一个bean definition验证失败时抛出异常的异常类。
9、org.springframework.beans.factory.serviceloader包含的接口和类
9.1 AbstractServiceLoaderBasedFactoryBean:FactoryBean的抽象基类,它是操作JDK1.6 ServiceLoader的基础工具。
9.2 ServiceFactoryBean:暴露指定配置的服务类的基础服务的FactoryBean,通过JDK1.6 serviceLoader基础类来获取这些服务。
9.3 ServiceListFactoryBean:暴露配置的服务类的所有基础服务的FactoryBea,表现为一组服务对象,可以通过JDK1.6 serviceLoader基础类来获取这些服务。
9.4 ServiceLoaderFactoryBean:暴露指定配置服务类的JDK1.6 serviceLoader的FactoryBean。
10、org.springframework.beans.factory.support包含的接口和类
10.1 DefaultListableBeanFactory:是beans包中最核心的一个类,ListableBeanFactory接口和BeanDefinitionRegistry接口的默认实现:基于beanDefinition对象的一个成熟的beanFactory。BeanDefinitionRegistry(在此包中)提供了beanDefinition的管理。AbstractAutowireCapableBeanFactory(在此包中)实现属性的自动绑定功能。ConfigurableListableBeanFactory(在org.springframework.beans.factory.config包中)提供了对bean定义的分析和修改的便利方法,同时也提供了对单例的预实例化。
Serializable接口是Java提供的序列化接口,是一个空接口,为对象提供标准的序列化和反序列化操作。它的源代码是public interface Serializable{},即什么都没有,是一个标识接口。在Java中的这个Serializable接口是给JVM看的,告诉JVM,我不做这个类的序列化了,你(JVM)给我序列化。当我们让实体类实现此接口,其实是告诉JVM此类可以被序列化,可被默认的序列化机制序列化。那什么是序列化,作用是什么?序列化就是将一个对象及其状态转换成字节码,保存起来(可以保存在数据库、内存、文件等),然后可以在适当的时候再将其状态恢复(也就是反序列化)。有两个应用场景:一是想把内存中的对象状态保存到一个文件或者数据库中,二是想将对象通过网络进行传输的时候。
DefaultListableBeanFactory是通过实现上述4个特定的功能的接口、抽象类来完成的,是一个成熟的bean factory。spring IOC容器的实现,从根源上是beanfactory,但真正可以作为一个独立使用的IOC容器还是DefaultListableBeanFactory,因此可以说DefaultListableBeanFactory是整个spring IOC的始祖。它可以作为一个单独的BeanFactory,也可作为自定义BeanFactory的父类。其继承关系如下图:
(1)类入口处提供了一个静态方法:
javaxInjectProviderClass=ClassUtils.forName("javax.inject.Provider",DefaultListableBeanFactory.class.getClassLoader());
ClassUtils(在https://www.xiaoyuani.com/里)提供了对类的实用方法,主要用在框架内部。这个静态方法返回了javax.inject.Provider的一个实例。 包 javax.inject 指定了获取对象的一种方法,该方法与构造器、工厂这些传统方法相比可以获得更好的可重用性、可测试性以及可维护性。此方法的处理过程就是大家熟知的依赖注入。javax.inject.Provider其语法:public interface Provider,提供了一个T的实例,通常作为一个依赖注入容器的父接口,可以注入任何类型的T,当然也可以注入Provider,相对于直接注入,有几个好处:检索多个实例,延迟或者选择性的检索一个实例,打破循环依赖,抽象的scope,可以从一个包含scope的更小的scope中检索一个实例。
(2)继承自AbstractAutowireCapableBeanFactory的方法
提供bean的创建(有construct方法),属性注值,绑定(包括自动绑定)和初始化。处理运行时bean引用,解析管理的集合,调用初始化方法。
最主要的实现的模板方法是:AutowireCapleBeanFactory类(在包org.springframework.beans. factory.config中,AbstractAutowireCapableBeanFactory实现此接口)中的方法resolveDependency(DependencyDescriptor, String, Set, TypeConverter)。这个方法用来实现类型的自动绑定AbstractAutowireCapableBeanFactory.copyConfigurationFrom(ConfigurableBeanFactory otherFactory)
(3)继承自ListableBeanFactory接口的方法
ListableBeanFactory(在包org.springframework.beans.factory中)是beanFactory接口的扩展接口,它可以枚举所有的bean实例,而不是客户端通过名称一个一个的查询得出所有的实例。要预加载所有的bean定义的beanfactory可以实现这个接口来。该接口定义了访问容器中Bean基本信息的若干方法,如查看Bean的个数、获取某一类型Bean的配置名、查看容器中是否包括某一Bean等方法;
继承自该接口的方法有:containsBeanDefinition()、findAnnotationOnBean() 、getBeanDefinitionCount() 、getBeanDefinitionNames()、getBeanNamesForType() 、getBeansOfType() 、getBeansWithAnnotation() 。
(4)继承自ConfigurableListableBeanFactory接口的方法
ConfigurableListableBeanFactory(在包org.springframework.beans.factory.config中)同时继承了ListableBeanFactory,AutowireCapableBeanFactory和ConfigurableBeanFactory,提供了对bean定义的分析和修改的便利方法,同时也提供了对单例的预实例化。
继承该接口的方法有:freezeConfiguration() 、getBeanDefinition()、ignoreDependencyInterface() 、ignoreDependencyType() 、isAutowireCandidate() 、isConfigurationFrozen() 、preInstantiateSingletons()、registerResolvableDependency() 。
(5)继承自BeanDefinitionRegistry接口的方法
BeanDefinitionRegistry:Spring配置文件中每一个节点元素在Spring容器里都通过一个BeanDefinition对象表示,它描述了Bean的配置信息。而BeanDefinition Registry接口提供了向容器手工注册BeanDefinition对象的方法。
继承该接口的方法有:containsBeanDefinition() 、getBeanDefinition()、getBeanDefinitionCount()、getBeanDefinitionNames() 、isBeanNameInUse() 、registerBeanDefinition() 、removeBeanDefinition() 。
(6)序列化支持
private void writeObject(java.io.ObjectOutputStream out);
private void readObject(java.io.ObjectInputStream in);
private void readObjectNoData()。
10.2 StaticListableBeanFactory:静态BeanFactory的实现,用来编程实现注册已经存在的单例实例。
10.3 AbstractBeanFactory:BeanFactory的抽象基类实现,提供ConfigurableBeanFactory SPI的全部功能。
在此简单介绍下SPI机制。SPI全称Service Provider Interface,一种服务发现机制。是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。SPI的作用就是为这些被扩展的API寻找服务实现。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。可以在运行时,动态为接口替换实现类。可以很容易的通过 SPI 机制为程序提供拓展功能。
10.4 AbstractAutowireCapableBeanFactory:抽象beanFactory的超类,它使用指定的RootBeanDefinition类的所有方法实现创建默认bean。
10.5 AbstractBeanDefinition:具体、成熟BeanDefinition类的基类,构造出RootBeanDefinition和ChildBeanDefinition的通用属性。
10.6 RootBeanDefinition:根BeanDefinition,表示在运行时期的spring BeanFactory中一个合并的BeanDefinition。
10.7 ChildBeanDefinition:从父类继承各种设置的bean的beanDefinition。
10.8 GenericBeanDefinition:通用BeanDefinition是一站式的标准bean Definition。
10.9 BeanDefinitionReader:bean definition解析器的简单接口。
10.10 BeanDefinitionReaderUtils:BeanDefinitionReader实现使用的工具方法类。
10.11 AbstractBeanDefinitionReader:实现了BeanDefinitionReader接口,是beanDefinitionReader的抽象基类。
10.12 PropertiesBeanDefinitionReader:简单属性格式的BeanDefinitionReader。
10.13 BeanDefinitionDefaults:简单保持BeanDefinition的默认属性类。
10.14 BeanDefinitionBuilder:使用建造者模式构建BeanDefinition的编程方法。
10.15 BeanDefinitionRegistry:持有beanDefinition的注册接口,例如RootBeanDefinition和ChildBeanDefinition实例。
10.16 SimpleBeanDefinitionRegistry:BeanDefinitionRegistry接口的简单实现。
10.17 BeanDefinitionRegistryPostProcessor:标准BeanFactoryPostProcessor SPI的扩展接口,允许在常规BeanFactoryPostProcessor检查之前注册更多bean definition。
10.18 BeanDefinitionResource:继承自AbstractResource,描述BeanDefinition的资源。在此介绍一下Spring使用的一种设计模式:装饰器模式。装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。装饰者可以在所委托被装饰者的行为之前或之后加上自己的行为,以达到特定的目的(如:功能的增强)。
10.19 BeanDefinitionValueResolver:主要用在bean工厂实施中,解析bean definition对象中的value,根据目标bean实例转换成真正的值。
10.20 BeanDefinitionValidationException:验证一个bean definition时出错抛出的异常。
10.21 BeanDefinitionOverrideException:BeanDefinitionStoreException一个子类,显示一个在尝试一个非法的重载。比如为同一个bean name注册一个新的definition,但是DefaultListableBeanFactory的isAllowBeanDefinitionOverriding却为false的时候。
10.22 ManagedArray:集合类,用来保存它所管理的array元素,它可以包含运行时期的bean引用(将被解析为bean对象)。
10.23 ManagedList:集合类,用来保存它所管理的List元素,它可以包含运行时期的bean引用(将被解析为bean对象)。
10.24 ManagedMap:集合类,用来保存它所管理的array值,它可以包含运行时期的bean引用(将被解析为bean对象) 。
10.25 ManagedSet:集合类,用来保存它所管理的set值,它可以包含运行时期的bean引用(将被解析为bean对象) 。
10.26 ManagedProperties:表示一个spring管理的属性实例,它支持父/子 definition的合并。
10.27 AutowireCandidateQualifier:解析自动绑定备选项Qualifier。
10.28 AutowireCandidateResolver:策略接口,对特定的依赖,这个接口决定一个特定的bean definition是否满足作为自动绑定的备选项。
10.29 SimpleAutowireCandidateResolver:继承自AutowireCandidateResolver,当出现不支持的注解时使用。
10.30 GenericTypeAwareAutowireCandidateResolver:继承自SimpleAutowireCandidateResolver,一个通用的AutowireCandidateResolver。
10.31 AutowireUtils:工具类,为具有自动装载能力的bean工厂提供一些有用的方法。
10.32 LookupOverride:表示可以重写一个在同一个IOC上下文中查找对象的方法。
10.33 MethodOverride:表示重写对象,它针对IOC容器所管理对象的方法的重写。
10.34 MethodOverrides:一组方法重写,决定了在运行时期对spring IOC容器管理对象的重写方法(如果存在的话)。
10.35 ReplaceOverride:MethodOverride的扩展,表示一个IOC容器方法的任意重写。
10.36 InstantiationStrategy:负责根据相应的根bean definition创建实例的接口。
10.37 SimpleInstantiationStrategy:BeanFactory中简单对象的初始化策略。
10.38 CglibSubclassingInstantiationStrategy:BeanFactory默认对象初始化策略。
10.39 BeanNameGenerator:对beanDefinition产生bean名称的策略接口。
10.40 DefaultBeanNameGenerator:BeanNameGenerator接口的默认实现,代理BeanDefinitionReaderUtils.generateBeanName(BeanDefinition, BeanDefinitionRegistry)方法。
10.41 SecurityContextProvider:运行在beanFactory中的安全Context的提供者。
10.42 SimpleSecurityContextProvider:SecurityContextProvider的简单扩展。
10.43 DefaultSingletonBeanRegistry:共享bean实例的通用注册,实现了SingletonBeanRegistry。
10.44 FactoryBeanRegistrySupport:一个支持单例注册(需要处理FactoryBean实例)的基类,集合了DefaultSingletonBeanRegistry对单例的管理功能。
10.45 ConstructorResolver:解析构造函数和工程方法的代理。对构造函数的解析主要通过参数匹配来实现。
10.46 DisposableBeanAdapter:对一个给定的bean实例进行销毁bean及进行销毁的相关工作的适配器。
这里简单介绍适配器模式:适配器就是为了实现接口而做的,如果不用适配器,你去实现接口的话,需要实现接口中的所有方法,这要那个就会带来一些麻烦,但是如果你使用了适配器,就可以定义一个类去实现接口,然后当你用哪个方法的时候直接继承该类就行了,这个类就是适配器了。适配器模式的意义是要将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的。而装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方式而提升性能。
10.47 MethodReplacer:一个可以重新定义IOC容器对象的所有方法的接口:方法注入是依赖注入的一种形式。
10.48 MergedBeanDefinitionPostProcessor:后处理回调接口,在运行时合并bean definition。
10.49 NullBean:一个空bean的内部表示,比如调用FactoryBean的getObect()或者其他的工厂方法返回的是null值。
10.50 ImplicitlyAppearedSingletonException:继承自IllegalStateException,一个内部使用的异常类,在ConstructorResolver引发,传递给初始化DefaultSingletonBeanRegistry。
11、org.springframework.beans.factory.wiring包含的接口和类
11.1 BeanConfigurerSupport:配置bean的便利基类,它可以对对象进行依赖注入。典型应用就是作为切面的子类使用。
11.2 BeanWiringInfo:保存特定类的bean的绑定元数据信息。在对注解和切面进行连接时使用。
11.3 BeanWiringInfoResolver:策略接口,能够根据给定的一个新初始化的bean对象解析bean的名称信息。在此简单介绍下策略模式:用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。通俗的讲就是遇到一种问题有多种解法的时候,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。
11.4 ClassNameBeanWiringInfoResolver:BeanWiringInfoResolver的简单默认实现,查找一个和全限定名同名的bean的名称。
12、org.springframework.beans.factory.xml包含的接口和类
12.1 AbstractBeanDefinitionParser:BeanDefinitionParser的抽象实现,提供了许多便利方法和模板方法,模板方法需要在子类进行重写来提供具体的逻辑实现。
12.2 AbstractSimpleBeanDefinitionParser:AbstractBeanDefinitionParser的简单实现,当将要解析元素的属性名和配置类的属性名一一对应的时候,可以用到该类。
12.3 AbstractSingleBeanDefinitionParser:BeanDefinitionParser的基类,需要解析和定义单独的BeanDefinition。
12.4 BeanDefinitionDecorator:DefaultBeanDefinitionDocumentReader用来处理自定义的,内嵌的标签的接口 。
12.5 BeanDefinitionDocumentReader:解析包含spring BeanDefinition的xml文件的SPI。
12.6 DefaultBeanDefinitionDocumentReader:BeanDefinitionDocumentReader接口的默认实现。
12.7 BeanDefinitionParser:DefaultBeanDefinitionDocumentReader用来处理自定义的,高层的标签的接口 。
12.8 BeanDefinitionParserDelegate:状态代理类,用来解析xml BeanDefinition。
12.9 BeansDtdResolver:spring bean dtd解析器EntityResolver的实现,用来从classpath或者jar文件加载dtd。
DTD(Documnet Type Definition)即文档类型定义,是一种XML约束模式语言,是XML文件的验证机制,属于XML文件组成的一部分。DTD 是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文件来看文档是否符合规范,元素和标签使用是否正确。
XSD(XML Schemas Definition)XML Schema语言也就是XSD。XML Schema描述了XML文档的结构。可以用一个指定的XML Schema来验证某个XML文档,以检查该XML文档是否符合其要求。文档设计者可以通过XML Schema指定一个XML文档所允许的结构和内容,并可据此检查一个XML文档是否是有效的。XML Schema本身是一个XML文档,它符合XML语法结构。可以用通用的XML解析器解析它。
XSD和DTD相比:DTD是使用非XML语法编写的,不可扩展,不支持命名空间,只提供非常有限的数据类型。XSD可跟据将来的条件可扩展,比DTD丰富和有用,用XML书写,支持数据类型,支持命名空间。
12.10 DefaultNamespaceHandlerResolver:NamespaceHandlerResolver接口的默认实现。
12.11 DelegatingEntityResolver:EntityResolver的实现,分别代理了dtd的BeansDtdResolver和xml schemas的 PluggableSchemaResolver。
12.12 NamespaceHandlerResolver:DefaultBeanDefinitionDocumentReader用来定位NamespaceHandler的接口。
12.13 PluggableSchemaResolver:继承自EntityResolver,使用一系列map文件将schema url解析到本地classpath资源。
12.14 ResourceEntityResolver:继承自EntityResolver,通过ResourceLoader来解析实体的引用。
12.15 XmlBeanDefinitionReader:Bean definition reader for XML bean definitions。
12.16 XmlBeanDefinitionStoreException:继承自BeanDefinitionStoreException。
12.17 XmlBeanFactory:过期,从spring 3.2 后推荐使用DefaultListableBeanFactory和XmlBeanDefinitionReader来代替它。
12.18 XmlReaderContext:ReaderContext的扩展,一般和XmlBeanDefinitionReader一起使用。
12.19 NamespaceHandler:实现了特定的URI命名空间。
12.20 NamespaceHandlerSupport:支持实现自定义的NamespaceHandler。
12.21 SimpleConstructorNamespaceHandler:单NamespaceHandler实现,它将自定义属性直接映射到bean属性。
12.22 SimplePropertyNamespaceHandler:简单NamespaceHandler实现,它将自定义属性直接映射到bean属性。
12.23 UtilNamespaceHandler:工具命名空间的NamespaceHandler。
12.24 DocumentDefaultsDefinition:简单的javaBean,它保存标准的spring xml文件中级别的属性,如:default-lazy-init,default-autowire等等。
12.25 DocumentLoader:加载xml文件的策略接口。
12.26 DefaultDocumentLoader:spring 的DocumentLoader默认实现。
12.27 ParserContext:传递一个beanDefinition 解析进程到此上下文,封装了所有的相关配置也包括状态。
三、BeanDefinition解析
其实Spring的org.springframework.beans包下面所有的类主要解决了三件事情:Bean的定义,Bean的创建,Bean的解析。对于使用者来说,唯一需要关心的就是Bean的创建,其他两个由Spring在内部帮你完成,对用户来说是透明的。
Bean的定义就是完整的描述了在Spring的配置文件中你定义节点中所有的信息,包括各种子节点。Bean的定义主要由BeanDefinition描述。当Spring成功解析你定义的节点后,在Spring的内部就被转换成BeanDefinition对象,以后所有的操作都是对这个对象完成的。
(一)BeanDefinition是什么?
BeanDefinition 描述了一个Bean实例,它包含了Bean 的属性值,构造器参数,同时包含有更多其他的创建这个Bean的信息。更通俗点来讲:BeanDefinition包含了创造一个Bean所需要的所有信息,属性,构造函数参数以及访问它们的方法,是一个Bean的元数据。
BeanDefinition在Spring中是用来描述Bean对象的,其本身不是一个bean实例,仅仅是包含bean实例的所有信息,比如属性值、构造器参数以及其他信息。Bean对象创建是根据BeanDefinition中描述的信息来创建的,BeanDefinition存在的作用是为了可以方便的进行修改属性值和其他元信息,比如通过BeanFactoryPostProcessor进行修改一些信息,然后在创建Bean对象的时候就可以结合原始信息和修改后的信息创建对象了。
(二)BeanDefinition属性
在讲BeanDefinition的属性之前,我们先一起看看BeanDefinition的继承体系。如下图,BeanDefinition继承图:
下面我们看看BeanDefinition的属性:
(1)id:Bean 的唯一标识名。它必须是合法的 XMLID,在整个 XML 文档中唯一。
(2)name:用来为 id 创建一个或多个别名。它可以是任意的字母符合。多个别名之间用逗号或空格分开。
(3)class:用来定义类的全限定名(包名+类名)。只有子类 Bean 不用定义该属性。
(4)parent:子类 Bean 定义它所引用它的父类 Bean。这时前面的 class 属性失效。子类 Bean 会继承父类 Bean 的所有属性,子类 Bean 也可以覆盖父类 Bean 的属性。注意:子类 Bean 和父类 Bean 是同一个 Java 类。
(5)abstract(默认为”false”):用来定义 Bean 是否为抽象 Bean。它表示这个 Bean 将不会被实例化,一般用于父类 Bean,因为父类 Bean 主要是供子类 Bean 继承使用。
(6)lazy-init(默认为“default”):用来定义这个 Bean 是否实现懒初始化。如果为“true”,它将在 BeanFactory 启动时初始化所有的 SingletonBean。反之,如果为“false”,它只在 Bean 请求时才开始创建 SingletonBean。
(7)autowire(自动装配,默认为“default”):它定义了 Bean 的自动装载方式。“no”:不使用自动装配功能。”byName”:通过 Bean 的属性名实现自动装配。”byType”:通过 Bean 的类型实现自动装配。“constructor”:类似于 byType,但它是用于构造函数的参数的自动组装。“autodetect”:通过 Bean 类的反省机制(introspection)决定是使用“constructor”还是使用“byType”。
(8)depends-on(依赖对象):这个 Bean 在初始化时依赖的对象,这个对象会在这个 Bean 初始化之前创建。
(9)init-method:用来定义 Bean 的初始化方法,它会在 Bean 组装之后调用。它必须是一个无参数的方法。
(10)destroy-method:用来定义 Bean 的销毁方法,它在 BeanFactory 关闭时调用。同样,它也必须是一个无参数的方法。它只能应用于 singletonBean。
(11)factory-method:定义创建该 Bean 对象的工厂方法。它用于下面的“factory-bean”,表示这个 Bean 是通过工厂方法创建。此时,“class”属性失效。
(12)factory-bean:定义创建该 Bean 对象的工厂类。如果使用了“factory-bean”则“class”属性失效。
(13)autowire-candidate:采用 xml 格式配置 bean 时,将元素的 autowire-candidate属性设置为 false,这样容器在查找自动装配对象时,将不考虑该 bean,即它不会被考虑作为其它 bean自动装配的候选者,但是该 bean 本身还是可以使用自动装配来注入其它 bean 的。
(14)MutablePropertyValues:用于封装标签的信息,其实类里面就是有一个 list,list里面是 PropertyValue 对象,PropertyValue 就是一个 name 和 value 属性,用于封装标签的名称和值信息。
(15)ConstructorArgumentValues:用于封装标签的信息,其实类里面就是有一个 map,map 中用构造函数的参数顺序作为 key,值作为 value 存储到 map 中。
(16)MethodOverrides:用于封装 lookup-method 和 replaced-method 标签的信息,同样的类里面有一个 Set 对象添加 LookupOverride 对象和 ReplaceOverride 对象。
(三)BeanDefinition实现类
bean definition的实现类共有三个,分别为ChildBeanDefinition,RootBeanDefinition,GenericBeanDefinition。
1、ChildBeanDefinition:是一种bean definition,它可以继承它父类的设置,即ChildBeanDefinition对RootBeanDefinition有一定的依赖关系。ChildBeanDefinition从父类继承构造函数参数值、属性值,并可以重写父类的方法,同时也可以增加新的属性或者方法。若指定初始化方法、销毁方法或者静态工厂方法,ChildBeanDefinition将重写相应父类的设置。depends on、 autowire mode、dependency check、singleton、lazy int一般由子类自行设定。
2、RootBeanDefinition:一个RootBeanDefinition定义表明它是一个可合并的bean definition:即在spring beanFactory运行期间,可以返回一个特定的bean。RootBeanDefinition可以作为一个重要的通用的bean definition 视图。
3、GenericBeanDefinition:可以有效替代ChildBeanDefinition的绝大部分使用场合。是一站式标准的bean definition,除了具有指定类、可选的构造参数值和属性参数这些其他bean definition一样的特性外,它还具有通过parenetName属性来灵活设置parent bean definition。通常,GenericBeanDefinition用来注册用户可见的bean definition(可见的bean definition意味着可以在该类 bean definition上定义post-processor来对bean进行操作,甚至为配置parent name做拓展准备)。RootBeanDefinition和ChildBeanDefinition用来预定义具有parent child关系的bean definition。
(四)BeanDefinition的载入和解析
对于IOC容器来说,这个载入过程,相当于把定义的BeanDefinition在IOC容器中转换成一个Spring内部表示的数据结构的过程。IOC容器对Bean的管理和依赖注入功能的实现,是通过对其持有的BeanDefinition进行各种操作来完成的。这些BeanDefinition数据在IOC容器中通过一个HashMap来保持和维护。
1、下面从DefaultListableBeanFactory入手,看下IOC容器是怎样完成BeanDefinition载入的。在开始分析之前,先回到IOC容器初始化入口,也就是看一下refresh方法。这个方法的最初是在FileSystemXmlApplicationContext的构造函数中被调用的,它的调用标志着容器初始化的开始,这些初始化化对象就是BeanDefinition数据。对于容器启动来说,refresh是一个很重要的方法。该方法在AbstractApplicationContext类(是FileSystemXMLApplicationContext的基类)中,它详细描述了整个ApplicationContext的初始化过程,比如BeanFactory的更新,MessageSource和PostProcessor的注册等等。这个执行过程为Bean的生命周期管理提供了条件。下面代码显示了对IOC容器执行refresh过程:
1 public void refresh() throws BeansException, IllegalStateException { 2 synchronized (this.startupShutdownMonitor) { 3 // Prepare this context for refreshing. 4 prepareRefresh(); 5 // 这里是在子类中启动refreshBeanFactory()的地方 6 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 7 // Prepare the bean factory for use in this context. 8 prepareBeanFactory(beanFactory); 9 10 try {11 // 设置BeanFactory的后置处理12 postProcessBeanFactory(beanFactory);.13 // 调用BeanFactory的后处理器,这些后处理器是在Bean定义中向容器注册的14 invokeBeanFactoryPostProcessors(beanFactory);15 // 注册Bean的后处理器,在Bean创建过程中调用16 registerBeanPostProcessors(beanFactory);17 // 对上下文中的消息源进行初始化18 initMessageSource();19 // 初始化上下文中的事件机制20 initApplicationEventMulticaster();21 // 初始化其他的特殊Bean22 onRefresh();23 // 检查监听Bean并且将这些Bean向容器注册24 registerListeners();25 // 实例化所有的(non-lazy-init)单件26 finishBeanFactoryInitialization(beanFactory);27 // 发布容器事件,结束Refresh过程28 finishRefresh();29 }30 31 catch (BeansException ex) {32 if (logger.isWarnEnabled()) {33 logger.warn("Exception encountered during context initialization - " +34 "cancelling refresh attempt: " + ex);35 }36 // 为防止Bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件Bean37 destroyBeans();38 // 重置 'active'标志39 cancelRefresh(ex);40 // Propagate exception to caller.41 throw ex;42 }43 44 finally {45 // Reset common introspection caches in Spring's core, since we46 // might not ever need metadata for singleton beans anymore...47 resetCommonCaches();48 }49 }50 }
2、进入到AbstractRefreshableAppliccationContext的refreshBeanFactroy()方法中,在这个方法中创建了BeanFactory。在创建IOC容器前,如果已经有容器存在,那么需要把已有的容器销毁和关系,保证refresh以后使用的都是新建立起来的IOC容器。
3、当建立好了当前的IOC容器以后,开始了对容器的初始化,比如BeanDefinition的载入。如下图所示:
这里调用的loadBeanDefinitions实际上是一个抽象方法,loadBeanDefinitions在AbstractRefreshableApplicationContext的子类AbstractXmlApplicationContext中的实现,在这个loadBeanDefinitions中,初始化了读取器XMLBeanDefinitionReader,然后把这个读取器在IOC容器中设置好。最后是启动读取器来完成BeanDefinition在IOC容器中的载入。接着就是loadBeanDefinitions调用的地方,首先得到BeanDefinition信息的Resource定位,然后直接调用XMLBeanDefinitionReader来读取,具体的载入过程是委托给BeanDefinitionReader来完成的。因为这里的BeanDefinition是通过XML文件来定义的,所以这里使用XMLBeanDefinitionReader来载入BeanDefinition到容器中。
4、通过以上对实现原理分析,在初始化FileSystemXmlApplicationContext的过程中是通过调用IOC容器的refresh来启动整个BeanDefinition的载入过程的,这个初始化是通过定义的XmlBeanDefinitionReader来完成的。同时我们知道实际使用IOC容器是DefaultListableBeanFactory,具体的Resource载入在XmlBeanDefinitionReader读入BeanDefinition时实现。因为Spring可以对应不同形式的BeanDefinition。由于这里使用的是Xml方式的定义,所有需要使用XMLBeanDefinitionReader。如果使用了其他的BeanDefinition方式,就需要使用其他的BeanDefinitionReader来完成数据的载入工作。
四、Bean默认标签解析
Spring的标签分为默认标签和自定义标签,Spring用节点的命名空间来判断是默认还是自定义标签。如果节点的命名空间为http://www.Springframework.org/schema/beans就认为是默认标签,否则就认为是自定义标签。
(一)默认标签
默认标签的解析在DefaultBeanDefinitionDocumentReader(在org.springframework.beans.factory.xml包中)类的parseDefaultElement方法中:
1 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { 2 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { 3 importBeanDefinitionResource(ele); 4 } 5 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { 6 processAliasRegistration(ele); 7 } 8 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { 9 processBeanDefinition(ele, delegate);10 }11 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {12 // recurse13 doRegisterBeanDefinitions(ele);14 }15 }
方法的逻辑很清晰,按默认标签是import、alias、bean、beans四类情况分别处理。其中,bean标签的解析最为复杂。
(二)bean标签的解析及注册(对应上述代码中processBeanDefinition(ele, delegate))
在此先简单介绍下bean标签,该标签用于声明一个类,在启动 Spring 框架的时候根据该配置的类创建对象到容器里面。属性如下所示:
<bean>标签:用于声明一个类,在启动Spring框架的时候根据该配置的类创建对象到容器里面
name:设置对象名(唯一标识符)
id:设置对象名(唯一标识符,功能和name一样)
class:用于指定对象对应的类名,如果不是实现类必须要将bean声明为抽象的!
scope:用于设置的对象的作用范围,可选参数如下:
*singleton:单例(默认)
对象出生:当程序加载配置文件创建容器时,创建
对象活着:只要容器还在,一直活着
对象死亡:应用停止,容器销毁,对象死亡
*prototype:多例(原型对象)
对象出生:当程序加载配置文件创建容器时创建(每次调用会创建一个新对象)
对象活着:只要对象被使用,一直活着
对象死亡:对象长时间不用,会被Java垃圾回收机制回收 (该对象不被容器管理)
*reqeust:web项目中,Spring将创建的对象放在request作用域中
*session:web项目中,Spring将创建的对象放在session作用域中
init-method:设置创建对象的时候,调用初始化方法
destroy-method:设置对象被回收时,调用注销的方法
<bean name="customerServiceImpl" class="cn.mgy.service.impl.CustomerServiceImpl"></bean>
首先我们来看看processBeanDefinition(ele,delegate)方法,对bean标签的解析进行一个大致上的流程了解:
1 /** 2 * Process the given bean element, parsing the bean definition 3 * and registering it with the registry. 4 */ 5 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { 6 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); 7 if (bdHolder != null) { 8 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); 9 try {10 // Register the final decorated instance.11 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());12 }13 catch (BeanDefinitionStoreException ex) {14 getReaderContext().error("Failed to register bean definition with name '" +15 bdHolder.getBeanName() + "'", ele, ex);16 }17 // Send registration event.18 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));19 }20 }
对上述代码进行分析:
1、BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement (ele);首先委托BeanDefinitionParserDelegate类(在org.springframework.beans. factory.xml包中)的parseBeanDefinitionElement()方法进行元素的解析,返回BeanDefinitionHolder类的实例bdHolder(return new BeanDefinitionHolder( beanDefinition, beanName, aliasesArray);)。方法调用完成后,bdHolder实例就包含我们配置的各种属性了,例如:class、name、id、alias之类的属性。
2、if (bdHolder != null)当返回的bdHolder不为空的情况下,若存在默认标签的子节点下面还有自定义的属性,还需要再次对自定义的标签进行解析。
3、BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());解析完成后,需要对解析后的bdHolder进行注册,注册委托给了BeanDefinitionReaderUtils(在包org.springframework.beans.factory.support中)的registerBeanDefinition方法。
4、getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));发出响应事件,通知相关的监听器,该bean加载完成。
(三)解析BeanDefinition(对应上述代码的BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele))
下面详细分析下BeanDefinitionHolder bdHolder = delegate. parseBeanDefinitionElement(ele);,进入BeanDefinitionParserDelegate的parseBeanDefinitionElement()方法:
1 /** 2 * Parses the supplied {@code <bean>} element. May return {@code null} 3 * if there were errors during parse. Errors are reported to the 4 * {@link org.springframework.beans.factory.parsing.ProblemReporter}. 5 */ 6 @Nullable 7 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { 8 /*********提取元素中的id以及name属性*********/ 9 //解析id属性10 String id = ele.getAttribute(ID_ATTRIBUTE);11 //解析name属性12 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);13 //分割name属性14 List<String> aliases = new ArrayList<>();15 if (StringUtils.hasLength(nameAttr)) {16 //将name属性的值通过,; 进行分割 转为字符串数字(即在配置文件中如配置多个name在此做处理)17 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);18 aliases.addAll(Arrays.asList(nameArr));19 }20 21 String beanName = id;22 // 如果ID为空 使用配置的第一个name属性作为ID23 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {24 beanName = aliases.remove(0);25 if (logger.isTraceEnabled()) {26 logger.trace("No XML 'id' specified - using '" + beanName +27 "' as bean name and " + aliases + " as aliases");28 }29 }30 31 if (containingBean == null) {32 // 校验beanName和aliases的唯一性33 // 内部核心为使用usedNames集合保存所有已经使用了的beanName和alisa34 checkNameUniqueness(beanName, aliases, ele);35 }36 /*********进一步解析其他所有属性到GenericBeanDefinition对象中*********/37 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);38 /*********如果检测到Bean没有指定beanName,那么使用默认规则为此Bean生成对应的beanName*********/39 if (beanDefinition != null) {40 if (!StringUtils.hasText(beanName)) {41 try {42 if (containingBean != null) {43 beanName = BeanDefinitionReaderUtils.generateBeanName(44 beanDefinition, this.readerContext.getRegistry(), true);45 }46 else {47 beanName = this.readerContext.generateBeanName(beanDefinition);48 // Register an alias for the plain bean class name, if still possible,49 // if the generator returned the class name plus a suffix.50 // This is expected for Spring 1.2/2.0 backwards compatibility.51 String beanClassName = beanDefinition.getBeanClassName();52 if (beanClassName != null &&53 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&54 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {55 aliases.add(beanClassName);56 }57 }58 if (logger.isTraceEnabled()) {59 logger.trace("Neither XML 'id' nor 'name' specified - " +60 "using generated bean name [" + beanName + "]");61 }62 }63 catch (Exception ex) {64 error(ex.getMessage(), ele);65 return null;66 }67 }68 String[] aliasesArray = StringUtils.toStringArray(aliases);69 /*********将获取到的信息封装到BeanDefinitionHolder的实例中*********/70 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);71 }72 73 return null;74 }
上述代码便是对默认标签解析的全过程。在对属性展开解析之前,Spring在外层又做了一个当前层的功能架构。重点看“进一步解析其他所有属性到GenericBeanDefinition对象中”,对应的代码为AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);,是一个重载函数,进入其代码:
1 /** 2 * Parse the bean definition itself, without regard to name or aliases. May return 3 * {@code null} if problems occurred during the parsing of the bean definition. 4 */ 5 @Nullable 6 public AbstractBeanDefinition parseBeanDefinitionElement( 7 Element ele, String beanName, @Nullable BeanDefinition containingBean) { 8 9 this.parseState.push(new BeanEntry(beanName));10 //解析class属性11 String className = null;12 if (ele.hasAttribute(CLASS_ATTRIBUTE)) {13 className = ele.getAttribute(CLASS_ATTRIBUTE).trim();14 }15 //解析parent属性16 String parent = null;17 if (ele.hasAttribute(PARENT_ATTRIBUTE)) {18 parent = ele.getAttribute(PARENT_ATTRIBUTE);19 }20 21 try {22 //创建用于承载属性的AbstractBeanDefinition类型的GenericBeanDefinition23 AbstractBeanDefinition bd = createBeanDefinition(className, parent);24 //硬编码解析默认bean的各种属性25 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);26 //提取description27 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));28 //解析元数据29 parseMetaElements(ele, bd);30 //解析lookup-Method属性31 parseLookupOverrideSubElements(ele, bd.getMethodOverrides());32 //解析replaced-method属性33 parseReplacedMethodSubElements(ele, bd.getMethodOverrides());34 //解析构造函数参数35 parseConstructorArgElements(ele, bd);36 //解析property子元素37 parsePropertyElements(ele, bd);38 //解析qualifier子元素39 parseQualifierElements(ele, bd);40 41 bd.setResource(this.readerContext.getResource());42 bd.setSource(extractSource(ele));43 44 return bd;45 }46 catch (ClassNotFoundException ex) {47 error("Bean class [" + className + "] not found", ele, ex);48 }49 catch (NoClassDefFoundError err) {50 error("Class that bean class [" + className + "] depends on not found", ele, err);51 }52 catch (Throwable ex) {53 error("Unexpected failure during bean definition parsing", ele, ex);54 }55 finally {56 this.parseState.pop();57 }58 59 return null;60 }
(四)创建用于承载属性的GenericBeanDefinition(对应上述代码的AbstractBeanDefinition bd = createBeanDefinition(className, parent))
BeanDefinition是一个接口,详见(三、BeanDefinition解析)。有三个对应它的实现:RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition。这三种实现均继承了AbstractBeanDefinition,其中BeanDefinition是配置文件元素标签在容器中的内部表示形式。元素有class、scope、lazy-init等配置属性。BeanDefinition则提供了相应的beanClass、scope、lazyInit属性,两者的属性是一一对应的。在配置文件中可以定义父和子,父用RootBeanDefinition表示,而子用ChildBeanDefinition表示,而没有父的就使用RootBeanDefinition表示。AbstractBeanDefinition对两者共同的类信息进行抽象。Spring通过BeanDefinition将配置文件中的配置信息转换为容器的内部表示,并将这些BeanDefinition注册到BeanDefinitionRegistry中。Spring容器的BeanDefinitionRegistry就像是Spring配置信息的内存数据库,主要以map形式进行保存,后续操作直接从BeanDefinitionRegistry中读取配置信息。要解析属性首先要创建用于承载属性的实例,也就是创建GenericBeanDefinition类型的实例。对应的代码为AbstractBeanDefinition bd = createBeanDefinition(className, parent),进入该函数:
1 /** 2 * Create a bean definition for the given class name and parent name. 3 * @param className the name of the bean class 4 * @param parentName the name of the bean's parent bean 5 * @return the newly created bean definition 6 * @throws ClassNotFoundException if bean class resolution was attempted but failed 7 */ 8 protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName) 9 throws ClassNotFoundException {10 11 return BeanDefinitionReaderUtils.createBeanDefinition(12 parentName, className, this.readerContext.getBeanClassLoader());13 }
继续跟踪下去:进入BeanDefinitionReaderUtils类(在包org.springframework.beans.factory.support中)中的函数:
1 /** 2 * Create a new GenericBeanDefinition for the given parent name and class name, 3 * eagerly loading the bean class if a ClassLoader has been specified. 4 * @param parentName the name of the parent bean, if any 5 * @param className the name of the bean class, if any 6 * @param classLoader the ClassLoader to use for loading bean classes 7 * (can be {@code null} to just register bean classes by name) 8 * @return the bean definition 9 * @throws ClassNotFoundException if the bean class could not be loaded10 */11 public static AbstractBeanDefinition createBeanDefinition(12 @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {13 14 GenericBeanDefinition bd = new GenericBeanDefinition();15 bd.setParentName(parentName);16 // parentName可能为空17 if (className != null) {18 //如果classLoader不为空,则使用传入的classLoader同一虚拟机加载类对象19 if (classLoader != null) {20 bd.setBeanClass(ClassUtils.forName(className, classLoader));21 }22 //否则只记录classLoader23 else {24 bd.setBeanClassName(className);25 }26 }27 return bd;28 }
至此createBeanDefinition() 已经解析完,而且我们也获得了用于承载属性的AbstractBeanDefinition了。
(五)解析各种属性(对应(三)解析BeanDefinition中的代码 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);)
上述已经创建了bean信息的承载实例,接下来就可以进行bean信息的各种属性分析了。进入parseBeanDefinitionAttributes方法,此方法是对Element所有的元素属性进行分析。该方法也在类BeanDefinitionParserDelegate中。
1 /** 2 * Apply the attributes of the given bean element to the given bean * definition. 3 * @param ele bean declaration element 4 * @param beanName bean name 5 * @param containingBean containing bean definition 6 * @return a bean definition initialized according to the bean element attributes 7 */ 8 public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, 9 @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {10 //scope和singleton两种属性只能指定其中之一,不可以同时出现,否则Spring会抛出异常11 if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {12 error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);13 }14 //解析scope属性15 else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {16 bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));17 }18 else if (containingBean != null) {19 //在嵌入BeanDefinition情况下且没有单独指定scope属性则使用父类默认的属性20 bd.setScope(containingBean.getScope());21 }22 //解析abstract属性23 if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {24 bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));25 }26 //解析lazy-init属性27 String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);28 if (isDefaultValue(lazyInit)) {29 lazyInit = this.defaults.getLazyInit();30 }31 //若没有设置或者设置成其他字符都会被设置为false32 bd.setLazyInit(TRUE_VALUE.equals(lazyInit));33 //解析autowire属性34 String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);35 bd.setAutowireMode(getAutowireMode(autowire));36 //解析depends-on属性37 if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {38 String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);39 bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));40 }41 //解析autowire-candidate属性42 String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);43 if (isDefaultValue(autowireCandidate)) {44 String candidatePattern = this.defaults.getAutowireCandidates();45 if (candidatePattern != null) {46 String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);47 bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));48 }49 }50 else {51 bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));52 }53 //解析primary属性54 if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {55 bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));56 }57 //解析init-method属性58 if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {59 String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);60 bd.setInitMethodName(initMethodName);61 }62 else if (this.defaults.getInitMethod() != null) {63 bd.setInitMethodName(this.defaults.getInitMethod());64 bd.setEnforceInitMethod(false);65 }66 //解析destroy-method属性67 if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {68 String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);69 bd.setDestroyMethodName(destroyMethodName);70 }71 else if (this.defaults.getDestroyMethod() != null) {72 bd.setDestroyMethodName(this.defaults.getDestroyMethod());73 bd.setEnforceDestroyMethod(false);74 }75 //解析factory-method属性76 if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {77 bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));78 }79 //解析factory-bean属性80 if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {81 bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));82 }83 84 return bd;85 }
在完成上面步骤后,也就是对bean所有的属性的解析后,将会把获取到的信息都封装到BeanDefinitionHolder中(在包org.springframework.beans.factory.config中)。查看其构造函数:
1 public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, @Nullable String[] aliases) {2 Assert.notNull(beanDefinition, "BeanDefinition must not be null");3 Assert.notNull(beanName, "Bean name must not be null");4 this.beanDefinition = beanDefinition;5 this.beanName = beanName;6 this.aliases = aliases;7 }
以上就是对bean标签的解析。
五、Bean的加载
下面一段简单的代码可以作为Spring代码加载的入口:MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");。Spring通过调用BeanFactory的getBean()方法来加载bean。getBean()方法的真正实现在类AbstractBeanFactory中(在org.springframework.beans.factory.support包中),看下该方法的源码:
1 /** 2 * Return an instance, which may be shared or independent, of the specified bean. 3 * @param name the name of the bean to retrieve 4 * @param requiredType the required type of the bean to retrieve 5 * @param args arguments to use when creating a bean instance using explicit arguments 6 * (only applied when creating a new instance as opposed to retrieving an existing one) 7 * @param typeCheckOnly whether the instance is obtained for a type check, 8 * not for actual use 9 * @return an instance of the bean 10 * @throws BeansException if the bean could not be created 11 */ 12 @SuppressWarnings("unchecked") 13 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, 14 @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { 15 /***************************(1)转换对应的beanName ***************************/ 16 // 提取对应的bean名称 17 final String beanName = transformedBeanName(name); 18 Object bean; 19 /***************************(2)尝试从缓存中加载单例 **************************/ 20 // 检查缓存中或者实例工厂中是否有对应的实例,直接尝试从缓存中获取或者singletonFactories中的ObjectFactory中获取 21 // 为什么会首先使用这段代码? 22 // 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖 23 // Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光 24 // 也就是将ObjectFactory加入到缓存中,一旦下个bean创建的时候需要依赖上个bean则直接使用ObjectFactory 25 Object sharedInstance = getSingleton(beanName); 26 if (sharedInstance != null && args == null) { 27 if (logger.isTraceEnabled()) { 28 if (isSingletonCurrentlyInCreation(beanName)) { 29 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + 30 "' that is not fully initialized yet - a consequence of a circular reference"); 31 } 32 else { 33 logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); 34 } 35 } 36 /******************************(3)bean的实例化 ******************************/ 37 // 如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。 38 // 有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例 39 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 40 } 41 // 缓存中取不到 42 else { 43 // 只有在单例情况下才会尝试解决循环依赖; 44 // 原型模式情况下,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为 45 // 对于B的创建再次返回到创建A,造成循环依赖,也就是下面的情况。对于“prototype”作用域Bean,Spring容器无法完成依赖注入, 46 // 因为“prototype”作用域的Bean,Spring容器不进行缓存,因此无法提前暴露一个创建中的Bean。 47 /**********************(4)原型模式(prototype)的依赖检查 **********************/ 48 if (isPrototypeCurrentlyInCreation(beanName)) { 49 throw new BeanCurrentlyInCreationException(beanName); 50 } 51 /*************************(5)检测parentBeanFactory **************************/ 52 //确认是否存在父类工厂 53 BeanFactory parentBeanFactory = getParentBeanFactory(); 54 //若父类不为空并且BeanDefinitionMap中所有加载的类不包括beanName,则尝试在父类工厂去检测 55 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 56 // Not found -> check parent. 57 String nameToLookup = originalBeanName(name); 58 if (parentBeanFactory instanceof AbstractBeanFactory) { 59 return ((AbstractBeanFactory) parentBeanFactory).doGetBean( 60 nameToLookup, requiredType, args, typeCheckOnly); 61 } 62 else if (args != null) { 63 // 委托给具有显示参数args的父工厂,递归到BeanFactory中寻找 64 return (T) parentBeanFactory.getBean(nameToLookup, args); 65 } 66 else if (requiredType != null) { 67 //委托给标准的父工厂getBean方法 68 return parentBeanFactory.getBean(nameToLookup, requiredType); 69 } 70 else { 71 return (T) parentBeanFactory.getBean(nameToLookup); 72 } 73 } 74 75 // 如果不仅仅是做类型检查而是创建bean,在这里进行记录 76 if (!typeCheckOnly) { 77 markBeanAsCreated(beanName); 78 } 79 80 try { 81 /***************(6)GenericBeanDefinition转为RootBeanDefinition **************/ 82 // 将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition, 83 // 如果指定BeanName是子Bean的话同时会合并父类的相关属性 84 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 85 checkMergedBeanDefinition(mbd, beanName, args); 86 /*********************************(7)寻找依赖 *******************************/ 87 //得到该bean所依赖的相关bean 88 String[] dependsOn = mbd.getDependsOn(); 89 // 若存在依赖则需要递归实例化依赖的bean 90 if (dependsOn != null) { 91 for (String dep : dependsOn) { 92 if (isDependent(beanName, dep)) { 93 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 94 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); 95 } 96 // 缓存依赖调用 97 registerDependentBean(dep, beanName); 98 try { 99 getBean(dep);100 }101 catch (NoSuchBeanDefinitionException ex) {102 throw new BeanCreationException(mbd.getResourceDescription(), beanName,103 "'" + beanName + "' depends on missing bean '" + dep + "'", ex);104 }105 }106 }107 /*********************(8)依据scope创建bean(最关键的一步) ********************/108 //到这里已经实例化玩依赖的bean了,所以开始实例化mbd本身了109 // singleton模式的创建110 if (mbd.isSingleton()) {111 sharedInstance = getSingleton(beanName, () -> {112 try {113 return createBean(beanName, mbd, args);114 }115 catch (BeansException ex) {116 // Explicitly remove instance from singleton cache: It might have been put there117 // eagerly by the creation process, to allow for circular reference resolution.118 // Also remove any beans that received a temporary reference to the bean.119 destroySingleton(beanName);120 throw ex;121 }122 });123 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);124 }125 126 else if (mbd.isPrototype()) {127 // prototype原型模式的创建(new)128 Object prototypeInstance = null;129 try {130 beforePrototypeCreation(beanName);131 prototypeInstance = createBean(beanName, mbd, args);132 }133 finally {134 afterPrototypeCreation(beanName);135 }136 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);137 }138 139 else {140 // 指定的scope上实例化bean141 String scopeName = mbd.getScope();142 final Scope scope = this.scopes.get(scopeName);143 if (scope == null) {144 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");145 }146 try {147 Object scopedInstance = scope.get(beanName, () -> {148 beforePrototypeCreation(beanName);149 try {150 return createBean(beanName, mbd, args);151 }152 finally {153 afterPrototypeCreation(beanName);154 }155 });156 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);157 }158 catch (IllegalStateException ex) {159 throw new BeanCreationException(beanName,160 "Scope '" + scopeName + "' is not active for the current thread; consider " +161 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",162 ex);163 }164 }165 }166 catch (BeansException ex) {167 cleanupAfterBeanCreationFailure(beanName);168 throw ex;169 }170 }171 /*********************************(9)类型转换 *******************************/172 // 检查需要的类型是否符合bean的实际类型173 if (requiredType != null && !requiredType.isInstance(bean)) {174 try {175 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);176 if (convertedBean == null) {177 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());178 }179 return convertedBean;180 }181 catch (TypeMismatchException ex) {182 if (logger.isTraceEnabled()) {183 logger.trace("Failed to convert bean '" + name + "' to required type '" +184 ClassUtils.getQualifiedName(requiredType) + "'", ex);185 }186 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());187 }188 }189 return (T) bean;190 }
上述1-9步在上述代码中已用分割线隔开,下面依次进行分析:
(1)转换对应的beanName转换对应的 beanName 是根据 getBean(String name) 方法传入的 name 参数进行的,传入的 name 并不一定是 beanName,可能是别名,也可能是 FactoryBean 。由于 name 的多种可能,Spring会进行对应的转换。这些转换包括: 1)去除 FactoryBean 的修饰符,一般就是去除 name 参数的 & 前缀;2)取指定的 alias 所表示的最终 beanName,例如别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则最后返回 C。实际是由org.springframework.beans.factory包中的BeanFactoryUtils类中的函数transformedBeanName()完成此功能。
(2)尝试从缓存中加载单例单例在Spring中的同一个容器内只会被创建一次,后续再获取 bean就直接从单例缓存中获取了。当然代码实现上首先进行尝试从缓存中进行加载,如果不成功再尝试从 singletonFactories 中加载,最后都不行才判断是没有创建过继而新建并放入缓存。之所以需要从 singletonFactories 中加载,因为在创建单例 bean 的时候会存在依赖注入 的情况,而在创建依赖 bean 的时候,为了避免循环依赖,Spring中创建 bean 的原则是不等 bean 创建完成就会提前将创建 bean 的 ObjectFactory 曝光加入到缓存中,一旦下一个 bean 创建的时候需要依赖该 bean 时则可以直接使用 ObjectFactory 作为依赖进行注入。
(3)bean的实例化如果从缓存中得到了 bean 的原始状态,则需要对 bean 进行实例化。缓存中记录的只是最原始的 bean 状态,并不是我们最终想要的 bean。例如:假如我们需要对工厂 bean 进行处理,那么这里得到的其实是工厂 bean 的初始状态,但我们真正需要的是工厂 bean 中定义的 factory-method方法中返回的 bean,而 getObjectForBeanInstance(sharedInstance, name, beanName, null) 就是完成这项工作。
(4)原型模式(prototype)的依赖检查Spring能够尝试解决的循环依赖问题只有单例模式下,对于原型模式的循环依赖问题Spring是没有方法解决的。因为在原型模式(prototype)下,如果 A 依赖 B,B 同时又依赖 A,那么就会出现创建 A 时因为创建依赖 B 而又要创建 A ,因为是多例的,所以会一直循环创建。Spring对于原型模式下的循环依赖会进行检测,检测代码为 isPrototypeCurrentlyInCreation(beanName) ,如果为 true,则会抛出异常。
(5)检测parentBeanFactory代码上的逻辑可以看出,如果从缓存中没有取到,那么直接转到父类工厂上去加载了。因为代码中的判断逻辑是:if (parentBeanFactory != null && !containsBeanDefinition(beanName)),前半部分还好,parentBeanFactory 不能为空,后半部分 !containsBeanDefinition(beanName)意思如果当前的 beanDefinitionMap (XML配置文件)中没有 beanName 对应的配置,就只能到 parentBeanFactory 中去尝试下,再递归的调用 getBean()方法了。
(6)GenericBeanDefinition转为RootBeanDefinition如果从缓存中获取不到,同时当前的 beanDefinitionMap 中存在对应 beanName 的配置,我们就可以依据包含有XML配置文件信息的 beanDefinition 进行创建 bean 了。从XML配置文件中读取到的 bean 信息是利用 GenericBeanDefinition 存储的,但是后面Spring对所有 bean 的后续处理都是针对于 RootBeanDefinition 的,所以需要进行转换,转换的同时如果父类 bean 不为空,则会一并合并父类的属性。
(7)寻找依赖因为 bean 的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置的成功依赖于其他的 bean,那么此时应该先加载依赖的 bean。所以在流程中,Spring初始化一个 bean,会先初始化其依赖的所有的其他 bean。
(8)依据scope创建beanSpring存在不同的 scope,其中默认的是 singleton,但是还有其他的配置像 prototype、request 等。在这一步中,Spring会根据配置进行采取对应的初始化策略。
(9)类型转换待 scope 创建完 bean 成功后,一般可以直接返回即可。但当传入 doGetBean 方法中的 requireType 参数不为空时,意味着我们对最后返回的 bean 有着类型上的要求。Spring一般通过类型转换器将第八步创建完成的 bean 转换为 requireType 指定的类型。Spring自身提供了一些转换器,用户也可以自己扩展转换器来满足需求。经过以上的九个步骤,bean 创建完成,这个时候返回的就是我们需要的bean。其中第八步最为关键:针对不同的 scope 进行 bean 的创建。
六、Bean的生命周期
Spring的IoC容器功能非常强大,负责Spring的Bean的创建和管理等功能。而Spring 的bean是整个Spring应用中很重要的一部分,了解Spring Bean的生命周期对我们了解整个spring框架会有很大的帮助。BeanFactory和ApplicationContext是Spring两种很重要的容器,前者提供了最基本的依赖注入的支持,而后者在继承前者的基础进行了功能的拓展,例如增加了事件传播,资源访问和国际化的消息访问等功能。下面介绍ApplicationContext和BeanFactory两种容器的Bean的生命周期。
ApplicationContext Bean生命周期:
ApplicationContext Bean生命周期流程ApplicationContext容器中,Bean的生命周期流程如上图所示,流程大致如下:
1、首先容器启动后,会对scope为singleton且非懒加载的bean进行实例化,
2、按照Bean定义信息配置信息,注入所有的属性,
3、如果Bean实现了BeanNameAware接口,会回调该接口的setBeanName()方法,传入该Bean的id,此时该Bean就获得了自己在配置文件中的id,
4、如果Bean实现了BeanFactoryAware接口,会回调该接口的setBeanFactory()方法,传入该Bean的BeanFactory,这样该Bean就获得了自己所在的BeanFactory,
5、如果Bean实现了ApplicationContextAware接口,会回调该接口的setApplicationContext()方法,传入该Bean的ApplicationContext,这样该Bean就获得了自己所在的ApplicationContext,
6、如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzation()方法,
7、如果Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法,
8、如果Bean配置了init-method方法,则会执行init-method配置的方法,
9、如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessAfterInitialization()方法,
10、经过流程9之后,就可以正式使用该Bean了,对于scope为singleton的Bean,Spring的IoC容器中会缓存一份该bean的实例,而对于scope为prototype的Bean,每次被调用都会new一个新的对象,其生命周期就交给调用方管理了,不再是Spring容器进行管理了,
11、容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法,
12、如果Bean配置了destroy-method方法,则会执行destroy-method配置的方法,至此,整个Bean的生命周期结束。
BeanFactory Bean生命周期流程图:
BeanFactory Bean生命周期流程:
1、容器寻找Bean的定义信息,并将其实例化。
2、使用依赖注入,Spring按照Bean定义信息配置Bean的所有属性。
3、如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的id。
4、如果实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
5、如果BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialization()方法将被调用。(需要手动进行注册!)
6、如果Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法。
7、如果Bean指定了init-method方法,就会调用init-method方法。
8、如果BeanPostProcessor和Bean关联,那么它的postProcessAfterInitialization()方法将被调用。(需要手动注册!)
9、现在Bean已经可以使用了。scope为singleton的Bean缓存在Spring IOC容器中。scope为prototype的Bean生命周期交给客户端。
10、销毁。如果Bean实现了DisposableBean接口,destory()方法将会被调用。如果配置了destory-method方法,就调用这个方法。
BeanFactoty容器中Bean的生命周期与ApplicationContext相比,有如下几点不同:
1、BeanFactory容器中,不会调用ApplicationContextAware接口的setApplicationContext()方法,
2、BeanPostProcessor接口的postProcessBeforeInitialzation()方法和postProcessAfterInitialization()方法不会自动调用,必须自己通过代码手动注册,
3、BeanFactory容器启动的时候,不会去实例化所有Bean,包括所有scope为singleton且非懒加载的Bean也是一样,而是在调用的时候去实例化。
Bean 实例创建时序图
Bean 对象关系建立流程图:
参考:
1. 《Spring源码深度解析》 郝佳 编著
2. 一天不进步就是退步 博客园
3. weixin_30439131 CSDN博客
4. 等一杯咖啡 CSDN博客