上一篇文章中给出了一个应用Spring的最简单的应用程序,下面就系统的说一下我对Spring的理解,如果有不对或者不完善的地方,希望大家能够指正,欢迎大家一起来讨论。
Spring是为创建企业级应用提供了一个轻量级的解决方案。Spring包含的内容实在是太多太多了,但是你可以只使用你需要的部分,因为Spring是模块化的。Spring还可以很好的和当下主流的框架进行集成,例如:请求转发的Struts2、持久化的Hibernate、Mybatis、JTA等等。
提到Spring,就不得不说IoC(控制反转,DI:依赖注入)和AOP(面向切面编程)。到底怎么理解这两个东西,这个不是一朝一夕就能理解的特别透彻的,需要在不断积累的过程中,逐渐加深对这个东西的理解,下面我简单的说一下我的理解。
IoC(Inversion of Control):控制反转,是使用思想,不是技术。谁控制谁,控制什么?什么东西被反转了?IoC创建对象,并控制这些对象,让依赖对象的获取方式被反转了!为什么呢?因为我们知道,一个复杂的系统是有很多的类,这些类之间相互协作,说的更直白一点就是:你这个类需要调用其他类提供的方法,这个时候我们通常都是通过new获取一个其他类的对象,这个工作是程序员自己去做的,更厉害一点的程序员可能会使用工厂模式或者其他设计模式,把获取对象的过程进行一个封装,总的来说获取对象的过程是程序员自己进行管理。在我们使用了Spring之后,我们不再需要管理如何创建依赖的对象,这个工作交给了IoC容器,我们只需要把我们依赖的bean注册在IoC容器,当我们需要的时候,通过IoC容器提供的方法,获取相关的依赖对象。相比于我们传统的获取对象的方式,是不是控制反转了,有程序员自己管理,变成了由Spring的IoC容器进行管理。它最大的好处就是解耦。
往往和IoC一起出现的还有一个DI(Dependency Injection):依赖注入。DI是有Martin Fowler提出来的,这是在2004年,在解释“IoC的控制反转了什么?”的时候,给的一个新的名称。其实就是IoC控制反转的一个更直白的名字:因为我们使用了Spring的IoC容器,对象之间依赖的Bean的创建都交给了IoC容器,在系统运行的过程中,我们需要向IoC容器获取我们依赖的bean,这个时候,IoC容器就会把我们需要的Bean注入到我们的类中,即应用程序依赖于IoC容器,需要IoC容器把外部资源(指的是应用程序依赖的对象、数据、文件等)注入到应用程序中去。这个概念相比于IoC控制反转应该说更容易理解一些。上面就是我对IoC和DI的理解,如果有不对的或者不清楚的地方,欢迎讨论指正。
下面结合一个简单的示例,来说明一下,有两个类A和B,B中有一个A的引用,B依赖A:
class A{ } class B{ private A a; public void setA(A a){ this.a = a; } }
传统方式我们需要自己创建对象,然后通过set方法,注入进去,在有了IoC容器之后,我们只需要简单的一句话:B b = getB();IoC容器会自动的把B对象依赖的A注入进去。
AOP(Aspect-Oriented Programming):面向切面编程。AOP其实是面向对象编程(OOP:Object Oriented Programing)思想的补充和完善。我们知道,OOP引进"抽象"、"封装"、"继承"、"多态"等概念,对万事万物进行抽象和封装,来建立一种对象的层次结构,它强调了一种完整事物的自上而下的关系。但是具体细粒度到每个事物内部的情况,OOP就显得无能为力了。比如日志功能。日志代码往往水平地散布在所有对象层次当中,却与它所散布到的对象的核心功能毫无关系。对于其他很多类似功能,如事务管理、权限控制等也是如此。这导致了大量代码的重复,而不利于各个模块的重用。PS:其实我现在对AOP有一定的了解,但是还不能够特别清楚的表达出来。。。。。
下面来看一下Spring官方参考文档中给出来的Spring框架的概述图:
Spring的核心容器主要有以下几个模块组成:spring-core,spring-beans,spring-context,spring-context-support,以及spring-expression(Spring Expression Language)。
Core(spring-core)模块和Beans(spring-beans)模块是Spring框架的基础部分,实现了IoC容器和依赖注入。其中的BeanFactory是典型的工厂模式的实现,他可以让你不用考虑去编写单件,可以把实际依赖关系通过配置文件的方式进行解耦。
Context(spring-context)模块是在Core和Beans模块基础之上的,它提供了Spring框架访问对象方法,它的原理和JNDI注册表类似。Context模块继承了Beans模块的特点,还增加了国际化的支持、事件传播、资源加载和透明的情况下创建应用上下文,例如创建一个Servlet容器。Context模块还支持Java EE的一些特性,例如EJB、JMX和基本的远程操作。ApplicationContext接口是Context模块的焦点。Spring-context-support提供整合第三方库到spring应用上下文的支持,这其中包括:缓存(EhCache,Guava,JCache)、mailing(JavaMail)、调度框架(CommonJ,Quartz)以及模板引擎(FreeMarker,JasperReports,Velocity)。
SpEL(spring-expression)模块提供了一种强大的表达式语言,这种表达式语言可以在运行时查询和操作对象。SpEL是对EL表达式的一种扩充。支持setting和getting属性值,属性赋值,方法调用,访问数组、集合、索引器中的内容,逻辑运算和四则运算,变量命名,从Spring的IoC容器中检索对象。
它还支持列表投影和选择,以及常见的列表聚合。
AOP模块提供了面向切面编程的支持,由于spring-aspects的存在,能够使得spring与AspectJ进行无缝对接。
数据访问/集成有JDBC、ORM、OXM、JMS以及事务组成。spring-jdbc提供了对JDBC的抽象,省略了冗长的JDBC代码。spring-tx模块提供了对声明式事务的支持。spring-orm提供了与其他ORM框架的集成支持,例如:JPA、JDO、Hibernate。
Web层包括spring-web、spring-webmvc、spring-websocket和spring-webmvc-portlet。spring-web模块提供了基本的web集成的功能,例如文件上传,通过servlet监听器和web上下文初始化IoC容器。spring-webmvc包括spring的MVC,支持REST风格的Web Service。
上面这一段基本上是参照spring官方文档的翻译,如果不对,或者翻译不恰当的地方,欢迎批评指正,希望能够和大家多多交流。