微信号:GitShare
微信公众号:爱折腾的稻草
如有问题或建议,请在公众号留言[1]
前续
为帮助广大SpringBoot用户达到“知其然,更需知其所以然”的境界,作者将通过SpringBoot系列文章全方位对SpringBoot2.0.0.RELEASE版本深入分解剖析,让您深刻的理解其内部工作原理。
No.1 Spring是什么
为了让更多的朋友了解Spring,首先科普一下Spring!有兴趣的朋友可以去Spring官网逛逛,地址是:https://spring.io/
The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications - on any kind of deployment platform.
Spring Framework为现代基于Java的企业应用程序提供了全面的编程和配置模型 - 在任何类型的部署平台上。
总的来说:Spring是一个分层的Java SE/EE应用一站式的轻量级开源框架。
No.2 Spring的优点
Spring的一个关键要素是应用程序级别的基础架构支持:Spring专注于企业应用程序的“管道”,以便团队可以专注于应用程序级业务逻辑,而无需与特定部署环境建立不必要的联系。
方便解耦,简化开发,通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码造成的程序耦合度高。
AOP编程的支持,通过Spring提供的AOP功能,方便进行面向切面编程。
声明式事务的支持,在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
方便程序的测试,可以用非容器依赖的编程方式进行几乎所有的测试工作。
方便集成各种优秀框架,Spring提供了对各种优秀框架的直接支持。
No.3 Sprnig的架构
整个Spring框架按其所属功能可以划分为五个主要模块,这五个模块几乎为企业应用提供了所需的一切,从持久层、业务层到表现层都拥有相应的支持,这就是Spring为什么是一站式框架。IoC和AOP是Spring的核心。
1、核心模块(Core Container)
Spring的核心模块实现了IoC的功能,它将类和类之间的依赖从代码中脱离出来,用配置的方式进行依赖关系描述。 由IoC容器负责类的创建,管理,获取等。BeanFactory接口是Spring框架的核心接口,实现了容器很多核心的功能。
Context模块构建于核心模块之上,扩展了BeanFactory的功能,包括国际化,资源加载,邮件服务,任务调度等多项功能。ApplicationContext是Context模块的核心接口。
表达式语言(Expression Language)是统一表达式语言(EL)的一个扩展,支持设置和获取对象属性,调用对象方法,操作数组、集合等。使用它可以很方便的通过表达式和Spring IoC容器进行交互。
2、AOP模块
Spring AOP模块提供了满足AOP Alliance规范的实现,还整合了AspectJ这种AOP语言级的框架。通过AOP能降低耦合。
3、数据访问集成模块(Data Access/Integration )
该模块包括了JDBC、ORM、OXM、JMS和事务管理
事务模块:该模块用于Spring管理事务,只要是Spring管理对象都能得到Spring管理事务的好处,无需在代码中进行事务控制了,而且支持编程和声明性的事务管理。
JDBC模块:提供了一个JBDC的样例模板,使用这些模板能消除传统冗长的JDBC编码还有必须的事务控制,而且能享受到Spring管理事务的好处。
ORM模块:提供与流行的“对象-关系”映射框架的无缝集成,包括Hibernate、JPA、MyBatis等。而且可以使用Spring事务管理,无需额外控制事务。
OXM模块:提供了一个对Object/XML映射实现,将java对象映射成XML数据,或者将XML数据映射成java对象,Object/XML映射实现包括JAXB、Castor、XMLBeans和XStream。
JMS模块:用于JMS(Java Messaging Service),提供一套 “消息生产者、消息消费者”模板用于更加简单的使用JMS,JMS用于用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
4、Web模块
该模块建立在ApplicationContext模块之上,提供了Web应用的功能。如文件上传、FreeMarker等。
Spring可以整合Struts2等MVC框架。Spring自己提供了MVC框架Spring MVC。
5、测试模块
Spring可以用非容器依赖的编程方式进行几乎所有的测试工作,支持JUnit和TestNG等测试框架。
No.4 什么是IOC
IOC是Inversion of Control的缩写,也称为“控制反转”。1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中,首先提出了IOC 这个概念。
简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。
IOC理论提出的观点大体是这样的:借助于“第三方”(IOC容器)实现具有依赖关系的对象之间的解耦。
2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。
控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。
所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。
小结:
所谓控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。
IOC(Inversion of Control)另外一种说法叫DI(Dependency Injection),即依赖注入。它并不是一种技术实现,而是一种设计思想。
从技术角度来看,IOC其实就是反射编程。通过类名(字符串)来动态生成类对象。
IoC容器:最主要是完成了对象的创建和依赖的管理注入。
No.5 Spring的IOC容器(BeanFaoctory体系)
BeanFactory作为最顶层的一个接口类,它定义了IOC容器的基本功能规范,其源码如下:
public interface BeanFactory {
/**
* 对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,如果需要得到工厂本身,需要转义
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* 根据bean的名字,获取在IOC容器中得到bean实例
*/
Object getBean(String name) throws BeansException;
/**
* 根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制
*/
T getBean(String name, @Nullable Class requiredType) throws BeansException;
/**
* 根据bean的名字和Class类型来得到bean实例,args实例化bean时的参数
*/
Object getBean(String name, Object... args) throws BeansException;
/**
* 根据bean的Class类型类获取bean实例
*/
T getBean(Class requiredType) throws BeansException;
/**
* 根据bean的Class类型类获取bean实例,args实例化bean时的参数
*/
T getBean(Class requiredType, Object... args) throws BeansException;
/**
* 提供对bean的检索,看看是否在IOC容器有这个名字的bean
*/
boolean containsBean(String name);
/**
* 根据bean名字得到bean实例,并同时判断这个bean是不是单例
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* [2.0.3新增]根据bean名字得到bean实例,并同时判断这个bean是不是原型
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* 检查给定名称的getBean调用是否将返回可分配给指定目标类型的对象。
*/
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
/**
* [2.0.1版本新增]检查给定名称的getBean调用是否将返回可分配给指定目标类型的对象。
*/
boolean isTypeMatch(String name, @Nullable Class typeToMatch) throws NoSuchBeanDefinitionException;
/**
* 得到bean实例的Class类型
*/
@Nullable
Class getType(String name) throws NoSuchBeanDefinitionException;
/**
* 得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
*/
String[] getAliases(String name);
}
用于访问Spring bean容器的根接口。
BeanFactory实现应尽可能支持标准bean生命周期接口,完整的初始化方法及其标准顺序是:
- 1、BeanNameAware的setBeanName
- 2、BeanClassLoaderAware的setBeanClassLoader
- 3、BeanFactoryAware的setBeanFactory
- 4、EnvironmentAware的setEnvironment
- 5、EmbeddedValueResolverAware的setEmbeddedValueResolver
- 6、ResourceLoaderAware的setResourceLoader(仅适用与运行时的应用上下文)
- 7、ApplicationEventPublisherAware的setApplicationEventPublisher (仅适用与运行时的应用上下文)
- 8、MessageSourceAware的setMessageSource (仅适用与运行时的应用上下文)
- 9、ApplicationContextAware的setApplicationContext (仅适用与运行时的应用上下文)
- 10、ServletContextAware'的setServletContext (仅适用与运行时的应用上下文)
- 11、 BeanPostProcessors的postProcessBeforeInitialization方法
- 12、InitializingBean的afterPropertiesSet
- 13、自定义一个初始化方法(init-method)
- 14、BeanPostProcessors的postProcessAfterInitialization方法
关闭BeanFactory时,以下生命周期方法适用:
- 1、DestructionAwareBeanPostProcessors的postProcessBeforeDestruction方法
- 2、DisposableBean's destroy
- 3、自定义一个销毁方法(destroy-method)
1、BeanFactory的继承关系
ListableBeanFactory
BeanFactory接口的扩展由bean工厂实现,提供容器内bean实例的枚举功能。HierarchicalBeanFactory
可以被作为分层结构中的一部分的bean工厂实现。提供父容器的访问功能。
public interface HierarchicalBeanFactory extends BeanFactory {
/**
* 返回其父工厂,如果没有返回Null
*/
@Nullable
BeanFactory getParentBeanFactory();
/**
* 返回当前bean工厂上下文是否存在给定bean名字的bean,忽略定义在其继承层次中的工厂上下文,只在当前层次中查找
*/
boolean containsLocalBean(String name);
}
AutowireCapableBeanFactory
BeanFactory接口的扩展将由能够自动装配的BeanFactory实现,前提是他们希望为现有bean实例公开此功能。
添加集成其他框架功能。如果集成WebWork则可以使用Spring对Actions等进行管理。SimpleJndiBeanFactory
基于JNDI的简单实现Spring的BeanFactory接口,不支持枚举bean定义。ConfigurableBeanFactory
是HierarchicalBeanFactory的子类,在其基础上提供了配置BeanFactory的功能。ConfigurableListableBeanFactory
是ListableBeanFactory、ConfigurableBeanFactory和AutowireCapableBeanFactory的子类,它提供了分析和修改bean定义以及预先实例化单例的功能。ApplicationContext
应用上下文接口,这个在Spring的Context一文中已经分析过了。
2、Spring中IOC容器的初始化
在Spring中IOC容器的初始化是有refresh()方法来启动的,主要有三个基本过程:
1.BeanDifinition的Resource定位
2.BeanDifinition的载入与解析
3.BeanDifinition在Ioc容器中的注册
No.6 IOC容器的缺点
IOC给我们带来的优点就不说了,主要看看其注意事项:
项目中引人第三方的IOC容器,对象的生成变得复杂;
由于IOC容器是通过反射来生成对象,所以会有一定的性能损耗;
Spring的IOC容器在使用时,需要配置大量的配置文件。
后记
为帮助广大SpringBoot用户达到“知其然,更需知其所以然”的境界,作者将通过SpringBoot系列文章全方位对SpringBoot2.0.0.RELEASE版本深入分解剖析,让您深刻的理解其内部工作原理。
本系列历史文章列表
1、[SpringBoot]利用SpringBoot快速构建并启动项目
2、[SpringBoot]详解SpringBoot应用的启动过程
3、[SpringBoot]深入浅出剖析SpringBoot的应用类型识别机制
4、[SpringBoot]深入浅出剖析SpringBoot中Spring Factories机制
5、[SpringBoot]详解SpringBoot中SpringApplication的run方法的前三步
6、[SpringBoot]图解Spring的Environment机制
7、[SpringBoot]源码解析SpringBoot应用Environment的构造过程
8、[SpringBoot]源码解析SpringBoot的Banner机制
9、[SpringBoot]图解SpringBoot的应用上下文机制
10、[SpringBoot]源码分析SpringBoot的异常处理机制
11、[SpringBoot]源码解析SpringBoot应用上下文的刷新处理
12、[SpringBoot]源码解析SpringBoot应用上下文前置处理
13、[SpringBoot]图解Spring的核心组件之Context
14、[SpringBoot]详解Spring的核心思想之AOP