作为Java开源世界的第一框架,Spring已经成为事实上的Java EE开发标准Spring框架最根本的使命是简化Java开发,所以学习、研究、掌握Spring框架成为每一位Java开发人员的必修课。而阅读源码则是学习Spring的最好方式之一。java
Spring 里面最重要的特性就是 Ioc,可能你还会说 aop。其实 aop 的实现也是基于 ioc。Ioc (Inversion of Control),即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。spring
关于 Spring IOC 源码分析的文章网上不少,如今我就来另辟蹊径。Spring Ioc 的对象扭转以及 涉及到的核心接口来分析一下它的源码实现。segmentfault
我把 Spring Ioc 的对象转换分为如下 4 个步骤:app
Resource -> BeanDefinition -> BeanWrapper -> Object
Resouce 实际上是一个接口,表明的是资源,在计算机里面从一个地方移动到另一个地方所须要的东西就是数据流,因此 Resource 实现了 InputStreamSource 接口,经过 InputStreamSource 接口能够获取到 Inputstream,这样就能够读取不一样的 Bean 定义了。框架
public interface InputStreamSource { InputStream getInputStream() throws IOException; }
Spring 能够定义不一样类型的 bean,最后均可以封装成 Resource 经过 IO 流进行读取。 Spring 能够定义类型的 bean 对象:源码分析
<bean>
标签。望文生义,很显示这个是 Bean 对象的定义。 Spring 经过不一样形式来定义 bean,最终会把这些定义转化成 BeanDefinition 保存在 Spring 容器当中进行依赖注入。下面咱们来看一下 BeanDefinition 的接口定义。学习
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { ConstructorArgumentValues getConstructorArgumentValues(); MutablePropertyValues getPropertyValues(); ... }
这个接口的定义很复杂可是,对于初始理解 spring ioc,只须要关心两个方法。ui
因此 Spring 支持构造器注入与 setter 依赖注入。this
一、构造器注入
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean>
二、setter注入
<bean id="exampleBean" class="examples.ExampleBean"> <!-- setter injection using the nested ref element --> <property name="beanOne"> <ref bean="anotherExampleBean"/> </property> <!-- setter injection using the neater ref attribute --> <property name="beanTwo" ref="yetAnotherBean"/> <property name="integerProperty" value="1"/> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
其实什么是依赖注入,简单来讲就是 Spring 帮咱们建立对象。把建立对象写死在 Java 文件变成了经过不一样的 Spring 配置能够注入不一样的值。建立对象的职责由 Java 文件变成了 Spring 配置文件。spa
下面我就问一个简单的问题,如何建立对象。可能你们呵呵一笑,建立对象这还不简单。
一、无参构造器
Object obj = new Object(); obj.setXxx(xxx);
二、有参构造器
Object obj = new Object(xxx, yyyy); obj.setXxx(xxx);
其实 Spring 也是这样来建立对象的,不信讲看 : (入口方法 BeanFactory#getBean
)
实例化对象返回 BeanWrapper,实际上是为了依赖注入服务也就是上面的第二步。 这个接口的功能仍是很复杂的,它继承了 4 个接口。
下面就来分别介绍一下这些接口的功能。
下面就是这个接口的定义。
public interface TypeConverter { <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException; <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException; <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field) throws TypeMismatchException; }
它的做用就是自动类型转换,由于 Spring 做得太无感知了。你也许尚未感受到它的存在。不要紧,我提示一下你应该就会明白。好比,声明一个用户对象这个对象既有 String 类型的名称,又有 Int 类型的年龄。 Spring 怎么知道属性的类型呢?这个就是 Spring 的自动类型转换。关于 Spring 的自动类型转换 我在以前就已经分析过了。
这个接口主要的做用是注册属性修改器(PropertyEditor),这个是 Java 内省里面的机制。
public interface PropertyEditorRegistry { void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor); void registerCustomEditor(Class<?> requiredType, String propertyPath, PropertyEditor propertyEditor); PropertyEditor findCustomEditor(Class<?> requiredType, String propertyPath); }
通常经过继承 java.beans.PropertyEditorSupport 来实现自定义的类型转换。在 Spring 内部有大量的实现,以下图所示:
public interface PropertyAccessor { boolean isReadableProperty(String propertyName); boolean isWritableProperty(String propertyName); cessor method failed Class<?> getPropertyType(String propertyName) throws BeansException; TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException; Object getPropertyValue(String propertyName) throws BeansException; void setPropertyValue(String propertyName, Object value) throws BeansException; void setPropertyValue(PropertyValue pv) throws BeansException; void setPropertyValues(Map<?, ?> map) throws BeansException; void setPropertyValues(PropertyValues pvs) throws BeansException; void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown) throws BeansException; void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException; }
PropertyAccessor 这个接口是判断对象中的某个属性是否可读/可写,而且能够定入或者读取某个属性的值。从这个接口定义咱们能够看出,它的使用其实就是真正用来依赖注入的。而后调用属性操做的写入操做,彻底依赖注入。
public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter { void setConversionService(ConversionService conversionService); ConversionService getConversionService(); ... }
这个接口的功能和 PropertyEditorRegistry 接口同样,只不事后者是经过 java 内省来进行类型自动转换,而 ConfigurablePropertyAccessor 接口是经过 Spring 本身定义的 org.springframework.core.convert.ConversionService 来做类型转换类型转换。在 Spring 中默认使用的是 DefaultConversionService 来做自动类型转换支持,而且内部还添加了不少默认的类型转换。
public class DefaultConversionService extends GenericConversionService { /** Java 8's java.util.Optional class available? */ private static final boolean javaUtilOptionalClassAvailable = ClassUtils.isPresent("java.util.Optional", DefaultConversionService.class.getClassLoader()); /** Java 8's java.time package available? */ private static final boolean jsr310Available = ClassUtils.isPresent("java.time.ZoneId", DefaultConversionService.class.getClassLoader()); /** Java 8's java.util.stream.Stream class available? */ private static final boolean streamAvailable = ClassUtils.isPresent( "java.util.stream.Stream", DefaultConversionService.class.getClassLoader()); public DefaultConversionService() { addDefaultConverters(this); } public static void addDefaultConverters(ConverterRegistry converterRegistry) { addScalarConverters(converterRegistry); addCollectionConverters(converterRegistry); converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry)); if (jsr310Available) { Jsr310ConverterRegistrar.registerJsr310Converters(converterRegistry); } converterRegistry.addConverter(new ObjectToObjectConverter()); converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry)); converterRegistry.addConverter(new FallbackObjectToStringConverter()); if (javaUtilOptionalClassAvailable) { converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry)); } } public static void addCollectionConverters(ConverterRegistry converterRegistry) { ConversionService conversionService = (ConversionService) converterRegistry; converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService)); converterRegistry.addConverter(new CollectionToArrayConverter(conversionService)); converterRegistry.addConverter(new ArrayToArrayConverter(conversionService)); converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService)); converterRegistry.addConverter(new MapToMapConverter(conversionService)); converterRegistry.addConverter(new ArrayToStringConverter(conversionService)); converterRegistry.addConverter(new StringToArrayConverter(conversionService)); converterRegistry.addConverter(new ArrayToObjectConverter(conversionService)); converterRegistry.addConverter(new ObjectToArrayConverter(conversionService)); converterRegistry.addConverter(new CollectionToStringConverter(conversionService)); converterRegistry.addConverter(new StringToCollectionConverter(conversionService)); converterRegistry.addConverter(new CollectionToObjectConverter(conversionService)); converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService)); if (streamAvailable) { converterRegistry.addConverter(new StreamConverter(conversionService)); } } private static void addScalarConverters(ConverterRegistry converterRegistry) { converterRegistry.addConverterFactory(new NumberToNumberConverterFactory()); converterRegistry.addConverterFactory(new StringToNumberConverterFactory()); converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter()); converterRegistry.addConverter(new StringToCharacterConverter()); converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter()); converterRegistry.addConverter(new NumberToCharacterConverter()); converterRegistry.addConverterFactory(new CharacterToNumberFactory()); converterRegistry.addConverter(new StringToBooleanConverter()); converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter()); converterRegistry.addConverterFactory(new StringToEnumConverterFactory()); converterRegistry.addConverter(Enum.class, String.class, new EnumToStringConverter((ConversionService) converterRegistry)); converterRegistry.addConverter(new StringToLocaleConverter()); converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter()); converterRegistry.addConverter(new StringToCharsetConverter()); converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter()); converterRegistry.addConverter(new StringToCurrencyConverter()); converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter()); converterRegistry.addConverter(new StringToPropertiesConverter()); converterRegistry.addConverter(new PropertiesToStringConverter()); converterRegistry.addConverter(new StringToUUIDConverter()); converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter()); } private static final class Jsr310ConverterRegistrar { public static void registerJsr310Converters(ConverterRegistry converterRegistry) { converterRegistry.addConverter(new StringToTimeZoneConverter()); converterRegistry.addConverter(new ZoneIdToTimeZoneConverter()); converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter()); } } }
关于 Spring 的自动类型转换 我在以前就已经分析过了。和 java 内省的原理是同样的。
public interface BeanWrapper extends ConfigurablePropertyAccessor { Object getWrappedInstance(); Class<?> getWrappedClass(); PropertyDescriptor[] getPropertyDescriptors(); PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException; ... }
这个接口就挺简单了,经过实现了上面的几个接口具备了依赖注入、类型转换注册(java 内省或者 Spring 自定义的 自动类型转换)。而后这个接口的主要的做用就是经过调用 getWrappedInstance
方法获取到当前实例对象,提供给属性的 writer 方法进行依赖注入。
writeMethod.invoke(getWrappedInstance(), value);
让咱们再来看一下 Spring 的对象扭转过过程:
Resource -> BeanDefinition -> BeanWrapper -> Object
相信基于以上的讲解,你们对于上面的过程可以理解 Spring IOC 的项目过程。在 Spring 进行 依赖注入的时候,首先把这种资源转化成 Resource 抽象,经过里面的 IO 流读取定义的 bean。而后再转化成 BeanDefinitioin,里面定义了包括构造器注入,以及 setter 注入的定义。最后经过 BeanWrapper 这个接口,首先获取定义的构造器注入属性,经过反射中的 Constructor 来建立对象。基于这个对象,经过 java 里面的内省机制获取到定义属性的属性描述器(PropertyDescriptor),调用属性的写入方法完成依赖注入,最后再调用 Spring 的自定义初始化逻辑,主要包括如下三个扩展点:
bean
标签经过 init-method 定义,也能够实现 InitializingBean但愿经过这篇文章,你们对 Spring IOC 有一个宏观上面的认识。这样就不会在复杂源码的逻辑中迷失。