这篇文章主要讲解了“java Spring源码分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java Spring源码分析”吧!
Spring 里面最重要的特性就是 Ioc,可能你还会说aop。其实aop的实现也是基于 ioc。Ioc (Inversion of Control),即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
关于 Spring IOC 源码分析的文章网上很多,现在我就来另辟蹊径。Spring Ioc 的对象扭转以及 涉及到的核心接口来分析一下它的源码实现。
Resource -> BeanDefinition -> BeanWrapper -> Object
1 Resource
Resouce 其实是一个接口,代表的是资源,在计算机里面从一个地方移动到另外一个地方所需要的东西就是数据流,所以 Resource 实现了 InputStreamSource 接口,通过 InputStreamSource 接口可以获取到 Inputstream,这样就可以读取不同的 Bean 定义了。
public interface InputStreamSource { InputStream getInputStream() throws IOException; }
Spring 可以定义不同类型的 bean,最后都可以封装成 Resource 通过 IO 流进行读取。 Spring 可以定义类型的 bean 对象:
XML:这是 Spring 最开始定义 bean 的形式
Annotation :由于通过 XML 定义 bean 的繁琐,Spring 进行了改进可以通过 @Component 以及基于它的注解来定义 bean。例如:@Service,@Controller等等,它们都可以定义 bean ,只不过语义更加明确。
Class:通过 @Configuration 与 @Bean 注解定义,@Configuration 代理 xml 资源文件,而 @Bean 代替 <bean> 标签。
Properties/yml:通过 @EnableConfigurationProperties 与 @ConfigurationProperties 来定义 bean。这种形式在 Spring boot 自动注入里面大量使用。
望文生义,很显示这个是 Bean 对象的定义。 Spring 通过不同形式来定义 bean,最终会把这些定义转化成 BeanDefinition 保存在 Spring 容器当中进行依赖注入。下面我们来看一下 BeanDefinition 的接口定义。
这个接口的定义很复杂但是,对于初始理解 spring ioc,只需要关心两个方法。
getConstructorArgumentValues:获取构造器注入定义的参数。
getPropertyValues:获取 setter 注入定义的参数。
所以 Spring 支持构造器注入与 setter 依赖注入。
其实什么是依赖注入,简单来说就是 Spring 帮我们创建对象。把创建对象写死在 Java 文件变成了通过不同的 Spring 配置可以注入不同的值。创建对象的职责由 Java 文件变成了 Spring 配置文件。
下面我就问一个简单的问题,如何创建对象。可能大家呵呵一笑,创建对象这还不简单。
其实 Spring 也是这样来创建对象的,不信讲看 : (入口方法 BeanFactory#getBean)
AbstractAutowireCapableBeanFactory#createBeanInstance() :通过反射 Constructor 调用配置的无参或者有参来创建对象实例。通过 BeanDefinition#getConstructorArgumentValues 获取,并返回 BeanWrapper 对象。
AbstractAutowireCapableBeanFactory#populateBean():,获取到定义的 bean 生成的所有的定义的setter注入的属性(BeanDefinition#getPropertyValues),然后遍历些这些属性,通过内省获取到对象所有的 属性描述器(PropertyDescriptor),获取到,属性的 PropertyDescriptor#getWriteMethod 方法,也就是 setter 方法,依赖注入值。如果是普通属性或者一些复杂对象,比如普通属性 String, int, long 或者 classpath:*转换为 Resource 复杂对象等等,直接注入即可;对于引用类型对象,继续依赖注入直到所有的属性是普通属性为止。
AbstractAutowireCapableBeanFactory#initializeBean():调用 Spring 自定义的初始化方法比如:BeanPostProcessor 扩展以及 init-method。
实例化对象返回 BeanWrapper,其实是为了依赖注入服务也就是上面的第二步。 这个接口的功能还是很复杂的,它继承了 4 个接口。
TypeConverter
PropertyEditorRegistry
PropertyAccessor
ConfigurablePropertyAccessor
下面就来分别介绍一下这些接口的功能。
下面就是这个接口的定义。
它的作用就是自动类型转换,因为 Spring 作得太无感知了。你也许还没有感觉到它的存在。没关系,我提示一下你应该就会明白。比如,声明一个用户对象这个对象既有 String 类型的名称,又有 Int 类型的年龄。 Spring 怎么知道属性的类型呢?这个就是 Spring 的自动类型转换。关于 Spring 的自动类型转换 我在之前就已经分析过了。
这个接口主要的作用是注册属性修改器(PropertyEditor),这个是 Java 内省里面的机制。
PropertyAccessor 这个接口是判断对象中的某个属性是否可读/可写,并且可以定入或者读取某个属性的值。从这个接口定义我们可以看出,它的使用其实就是真正用来依赖注入的。然后调用属性操作的写入操作,完全依赖注入。
这个接口的功能和 PropertyEditorRegistry 接口一样,只不过后者是通过 java 内省来进行类型自动转换,而 ConfigurablePropertyAccessor 接口是通过 Spring 自己定义的 org.springframework.core.convert.ConversionService 来作类型转换类型转换。在 Spring 中默认使用的是 DefaultConversionService 来作自动类型转换支持,并且内部还添加了很多默认的类型转换。
关于 Spring 的自动类型转换 我在之前就已经分析过了。和 java 内省的原理是一样的。
这个接口就挺简单了,通过实现了上面的几个接口具有了依赖注入、类型转换注册(java 内省或者 Spring 自定义的 自动类型转换)。然后这个接口的主要的作用就是通过调用 getWrappedInstance 方法获取到当前实例对象,提供给属性的 writer 方法进行依赖注入。
writeMethod.invoke(getWrappedInstance(), value);
感谢各位的阅读,以上就是“java Spring源码分析”的内容了,经过本文的学习后,相信大家对java Spring源码分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。