前面对Spring5.1进行了编译(https://blog.csdn.net/qq_20395245/article/details/105348043),接下来是学习spring 源码(指spring framework),在学习源码之前,先分享一些关于Spring的应用,这有助于更好理解源码,本篇将先从Spring应用开始。
Spring Framework:从https://spring.io/projects/spring-framework官方可知,Spring框架为现代基于java的企业应用程序提供了一个全面的编程和配置模型—适用于任何类型的部署平台。Spring framework包含很多重要的特性,其中就包含最核心的DI(dependency injection),AOP,Spring MVC等,这里将对DI进行应用学习。
什么是Spring DI?与IOC有什么区别:DI是dependency injection的缩写,称为“依赖性注入”;IOC是Inversion of Control的缩写,称为“控制反转”。根据Spring官方描述(https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html)DI与IOC是同一个意思。
什么是Spring容器,与IOC容器的区别?从官方文档中对Spring容器以及IOC容器的介绍,实际上Spring容器就可以理解为是IOC容器。Spring容器负责实例化、配置和组装bean。容器通过读取配置元数据获取关于要实例化、配置和组装哪些对象的指令。配置元数据用XML、Java注释或Java代码表示。它允许您表达组成应用程序的对象以及这些对象之间丰富的相互依赖关系。
这里也就引出了另一个概念:
什么是Class,Object以及Bean?我们使用Spring时经常会听到Bean这个概念,那Class,普通的Object对象以及Spring Bean对象之间有什么联系和区别呢。实际上Class只是二进制字节码,通过类加载器加载初始化之后会变成一个具体的类对象(也就是普通object对象),但是这个object对象要想成为一个Spring Bean,则需要经过一个完整的Spring生命周期,从文档可知:
上图显示了Spring如何工作的高级视图。您的应用程序类与配置元数据相结合,这样,在创建并初始化ApplicationContext之后,您就拥有了一个完全配置和可执行的系统或应用程序。
Spring IoC容器使用配置元数据的一种形式。此配置元数据表示作为应用程序开发人员,您如何告诉Spring容器实例化、配置和组装应用程序中的对象。
也就是说普通Object(POJOs)要想成为一个Bean,需要配合配置元数据(Configuration Metadata),通过Spring容器进行各种内部过程,最终产生出完整配置可随时提供使用的对象,这个对象就是Bean。
从这个过程可以知道配置元数据是重要的一步,那么什么是配置元数据呢,Spring都有哪些方式呢?这些在1.2.1. Configuration Metadata章节有描述:
以Spring发布的版本,大致目前可以分为3种:
1)Spring1.X版本(XML-based configuration):只能基于XML的方式进行配置,众所周知就是通过spring.xml的方式使用<bean>标签等声明:
2)直到Spring2.5版本,开始出现基于注解的配置(Annotation-based Configuration),例如@required,@AutoWire,@Resources,@Component等方式可以在类,方法,属性等地方进行注解式声明,极大简化了开发。
3)随着Spring发展,在Spring3.0之后开始出现基于Java Config(java-based configuration),这种方式使用 @Configuration,
@Bean,@Import,@DependsOn等注解,如SpringBoot使用了大量的Java Config就是基于这种方式,目前官方也建议更多的开发者使用这种方式。
对于这3种方式,关于怎么使用可以参考1.2.3. Using the Container章节。接下来非常重要,需要继续对Bean进行描述(文档1.3描述)。
1.3. Bean Overview
在Spring容器中,一个bean定义被表示为BeanDefinition对象(并不是直接通过new就会直接产生bean的),下面两图分别是普通类和bean的实例化过程对比
在Spring中对Bean的初始化过程很复杂,其中就有一个很重要的概念就是BeanDefinition,BeanDefinition是对Bean的描述,其中包含(其他信息)以下元数据:
可以这样理解,BeanDefinition是对Bean的一种描述,记录一个Bean所拥有的一些特性,在BeanDefinition的属性中,我们现在需要着重关注Autowiring mode属性,这个是一个Bean自动注入模式的描述。
什么是Bean自动注入?在解释Bean自动注入之前,让我们先通过一个demo了解一下通过XML注入的方式,
如我的demo工程中,service包下创建两个service类,其中LiuBeiService中会注入ZhangfeiService(这里只提ZhangfeiService的Setter方法),然后在spring.xml中分别声明这两个service类的bean,并且把ZhangfeiService对应的bean注入到LiuBeiService对应的bean中,这样LiuBeiService中就可以获取到对应的ZhangfeiService bean对象了,在Test.java中启动spring容器加载spring.xml,并从容器中获取LiuBeiServiceBean,打印注入的ZhangfeiService bean对象,可以得到结果:
这个过程的特点是通过XML配置,并且需要在spring.xml中手动将ZhangfeiService bean通过<property>标签注入到LiuBeiService Bean当中,然后这个ZhangfeiService才会在LiuBeiService的Setter方法中注入到属性中,这个过程我们姑且可以理解为“手动注入”方式(官方并没有为这种方式这么命名)。为什么要举这个demo的例子呢,是因为接下来要说的“自动注入”就不需要像这个手工注入需要人为干预,通过配置可以直接进行注入。
那怎么自动注入呢?这就回到BeanDefinition的属性Autowiring mode注入模式,注意这个自动注入模式也仅基于XML配置的方式才存在。根据文档1.4.5. Autowiring Collaborators,注入模式有四种,分别是no,byName,byType以及constructor,默认是no不注入。
未完待完善中...