详解Spring框架的核心思想之IOC

微信号: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中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

  • 方便程序的测试,可以用非容器依赖的编程方式进行几乎所有的测试工作。

    扫描二维码关注公众号,回复: 2156086 查看本文章
  • 方便集成各种优秀框架,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<T> requiredType) throws BeansException;
    /**
     * 根据bean的名字和Class类型来得到bean实例,args实例化bean时的参数
     */

    Object getBean(String name, Object... args) throws BeansException;
    /**
     * 根据bean的Class类型类获取bean实例
     */

    <T> getBean(Class<T> requiredType) throws BeansException;
    /**
     * 根据bean的Class类型类获取bean实例,args实例化bean时的参数
     */

    <T> getBean(Class<T> 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版本深入分解剖析,让您深刻的理解其内部工作原理。

本系列历史文章列表


图注:爱折腾的稻草


猜你喜欢

转载自blog.51cto.com/13836814/2141933