本节要点:
- Spring简介
- Spring特点
- Spring框架组成
- IOC和DI概念
- 项目中如何引入Spring框架
1 spring简介
spring:春天,寓意给软件行业带来了春天,由Rod Johnson提出
提出目的:解决企业应用开发的复杂性。
作用范围:任何Java应用 。
提出理念:使现有的技术更加实用,不去重复造轮子,让现有的框架运用更加合理。Struts和hibernate没有任何联系,所有spring最初的目的就是联系struts和hibernate,让他们运用的更好,本身就是一个大杂烩整合现有的框架技术。
2 spring特点(优点)
- 非侵入性:指spring框架的API不会在业务逻辑上出现
- 容器:spring提供容器功能,使用容器管理对象的生命周期,以及对象与对象之间的依赖关系。
- IOC:控制反转,即依赖关系的转移,如果以前都是依赖于实现,那么现在反转为依赖于抽象,其核心思想就是要面向接口编程。
- 依赖注入:对象与对象之间依赖关系的实现,包括接口注入、构造注入、set方法注入。在spring中只支持后两种。
- Aop:面向切面编程,将日志、安全、事务管理等服务(功能)理解成一个“切面”,以前这些服务通常是直接写在业务逻辑的代码中的,它有两个缺点:首先是业务逻辑不纯净,其次是这些服务被很多业务逻辑反复使用,不能做到复用。AOP解决了上述问题,可以把这些服务剥离出来形成一个“切面” ,可以实现复用;然后将“切面”动态地插入到业务逻辑中,让业务逻辑能够更方便地使用“切面”提供的服务。
还有一些其他的特点比如:对框架的支持,对JDBC的封装与简化,提供事务管理功能,对JNDI、mail等服务进行封装等。
3 spring框架组成
如果作为一个整体,这些模块为你提供了开发企业应用所需的一切。但你不必将应用完全基于Spring框架。你可以自由地挑选适合你的应用的模块而忽略其余的模块。
就像你所看到的,所有的Spring模块都是在核心容器之上构建的。容器 定义了Bean是如何创建、配置和管理的——更多的Spring细节。当你配置你的应用时,你会潜在地使用这些类。但是作为一名开发者,你最可能对影响容 器所提供的服务的其它模块感兴趣。这些模块将会为你提供用于构建应用服务的框架,例如AOP和持久性。
核心容器
这是Spring框架最基础的部分,它提供了依赖注入 (DependencyInjection)特征来实现容器对Bean的管理。这里最基本的概念是BeanFactory,它是任何Spring应用的核 心。BeanFactory是工厂模式的一个实现,它使用IoC将应用配置和依赖说明从实际的应用代码中分离出来。
应用上下文(Context)模块
核心模块的BeanFactory使Spring成为一个容器,而上下文模块使它成为一个框架。这个模块扩展了BeanFactory的概念,增加了对国际化(I18N)消息、事件传播以及验证的支持。
另外,这个模块提供了许多企业服务,例如电子邮件、JNDI访问、EJB集成、远程以及时序调度(scheduling)服务。也包括了对模版框架例如Velocity和FreeMarker集成的支持。
Spring的AOP模块
Spring在它的AOP模块中提供了对面向切面编程的丰富支持。这个模 块是在Spring应用中实现切面编程的基础。为了确保Spring与其它AOP框架的互用性,Spring的AOP支持基于AOP联盟定义的API。 AOP联盟是一个开源项目,它的目标是通过定义一组共同的接口和组件来促进AOP的使用以及不同的AOP实现之间的互用性。通过访问他们的站点,你可以找 到关于AOP联盟的更多内容。
Spring的AOP模块也将元数据编程引入了Spring。使用Spring的元数据支持,你可以为你的源代码增加注释,指示Spring在何处以及如何应用切面函数。
JDBC抽象和DAO模块
使用JDBC经常导致大量的重复代码,取得连接、创建语句、处理结果集,然后关闭连接。Spring的JDBC和DAO模块抽取了这些重复代码,因此你可以保持你的数据库访问代码干净简洁,并且可以防止因关闭数据库资源失败而引起的问题。
这个模块还在几种数据库服务器给出的错误消息之上建立了一个有意义的异常层。使你不用再试图破译神秘的私有的SQL错误消息!
另外,这个模块还使用了Spring的AOP模块为Spring应用中的对象提供了事务管理服务。
对象/关系映射集成模块
对那些更喜欢使用对象/关系映射工具而不是直接使用JDBC的 人,Spring提供了ORM模块。Spring并不试图实现它自己的ORM解决方案,而是为几种流行的ORM框架提供了集成方案,包括 Hibernate、JDO和iBATIS SQL映射。Spring的事务管理支持这些ORM框架中的每一个也包括JDBC。
Spring的Web模块
Web上下文模块建立于应用上下文模块之上,提供了一个适合于Web应用的上下文。另外,这个模块还提供了一些面向服务支持。例如:实现文件上传的multipart请求,它也提供了Spring和其它Web框架的集成,比如Struts、WebWork。
Spring的MVC框架
Spring为构建Web应用提供了一个功能全面的MVC框架。虽然Spring可以很容易地与其它MVC框架集成,例如Struts,但Spring的MVC框架使用IoC对控制逻辑和业务对象提供了完全的分离。
它也允许你声明性地将请求参数绑定到你的业务对象中,此外,Spring的MVC框架还可以利用Spring的任何其它服务,例如国际化信息与验证。
4 IOC和DI的概念
4.1 ioc--inversion of control控制反转
IoC是Spring的核心概念,控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。
当某个java实例(调用者)需要另一个java实例(被调用者)时,在传统的程序设计过程中,通常有由调用者来创建被调用者的实例,而控制反转则转移了控制权,既把调用者的创建转移到了外部容器(spring容器)。
简单实现控制反转案例:
//UserDao public interface UserDao { public void getUser(); } //UserDaoImpl public class UserDaoImpl implements UserDao { @Override public void getUser() { System.out.println("get user dates"); } } //UserService public interface UserService { public void getUser(); } //UserServiceImpl public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void getUser() { userDao.getUser(); } } //测试 public class Test { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); userService.setUserDao(new UserDaoOracleImpl()); userService.getUser(); } }
对象由原来的程序创建,变成程序接收对象;
程序员的主要精力集中于业务实现;
实现了service层和dao层的解耦,没有直接的依赖关系,如果dao层实现发生改变,应用程序本身不需要改变。
4.2 Dependency Injection(依赖注入)
IoC也是一种设计模式,有Dependency Injection(依赖注入)和Service Locator(服务定位器)两种实现方式, Spring框架采用依赖注入实现IoC。
依赖注入是在运行期,由外部容器动态地将依赖对象注入到组件中。即通过使用Spring框架,开发人员将不必在自己的代码中维护对象之间的依赖关系,只需在配置文件中进行设定, Spring会自动依据配置信息来维护对象之间的依赖关系。
5 IOC容器
5.1 IOC容器概述
Spring的IoC容器实现了控制反转,即在开发过程中,开发人员不需要关心容器是怎样的,也不需要调用容器的任何API。容器会自动进行被管理对象的初始化及对象之间依赖关系的维护。
在Spring中,最重要的是两个包,提供了IoC容器的基本功能
- org.springframework.beans
- org.springframework.context
5.2 IOC容器的工作原理
org.springframework.beans.factory.BeanFactory 是Spring 容器(也叫Spring
IoC 容器)的实际代表者,BeanFactory 是IoC 容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。整个IoC 容器就是一个大的工厂,为应用程序提供bean。
从上图可以看到,我们可以在Spring IoC 容器中配置应用程序中所需要的信息,如POJO 对象,这些对象(Bean)之间相互依赖关系,最终产出以备使用的对象。
5.3 BeanFactory接口及常用实现类XmlBeanFactory
BeanFactory接口提供了多个实现类来供开发人员使用,最常使用的是org.springframework.beans.factory.xml.XmlBeanFactory类,是通过XML格式的文件来配置Bean对象以维护对象之间的关系。
使用XML格式的配置文件时,配置文件的最顶层是<beans>元素,其内部包含一个或多个<bean/>元素,其中每一个<bean/>元素定义了一个bean的实例化信息以及与其他bean之间的关系
。
BeanFactory接口中的几个基本方法:
- Boolean
containsBean(String name)
判断Spring容器是否包含id为name的Bean实例
- Class getType(String name)
返回容器中指定Bean实例的类型
- Object
getBean(String name)
返回以给定名字注册的bean实例。根据bean的配置情况,如果为singleton模式将返回一个共享的实例,否则将返回一个新建的实例。如果没有找到指定的bean,该方法可能会抛出BeansException异常(实际上将抛出NoSuchBeanDefinitionException异常),在对bean进行实例化和预处理时也可能抛出异常
注:在实际的Web应用开发中,不需开发人员自己进行容器的初始化,生成BeanFactory对象,只需在web.xml文件中进行简单配置既可。
5.4 ApplicationContext接口及常用实现类
大部分时候,我们都不会使用BeanFactory实例作为Spring容器,而是使用ApplicationContext实例作为容器,该容器被称为Spring上下文。ApplicationContext是BeanFactory子接口,它增强了BeanFactory的功能。
- ApplicationContext
接口常用的实现类:
ClassPathXmlApplicationContext:从类路径中的XML文件载入上下文定义信息,把上下文定义文件当成类路径文件,例:
ApplicationContext context=new
ClassPathXmlApplicationContext(“beans- config.xml”);
- FileSystemXmlApplicationContext:从文件系统中的XML文件载入上下文信息,例:
ApplicationContext context=new FileSystemXmlApplicationContext(“d:/sp/beans-config.xml”);
区别:
FileSystemXmlApplicationContext只能在指定的路径寻找文件beans-config.xml;
ClassPathXmlApplicationContext可在整个类路径中寻找。
- XmlWebApplicationContext:从web系统中的XML文件载入载入上下文定义信息
5.5 BeanFactory和ApplicationContext的区别
ApplicationContext与BeanFactory都是Spring容器,职责都有实例化、定位、配置应用程序中的对象及建立这些对象间的依赖,但ApplicationContext提供更多功能:
- ApplicationContext继承MessageResource接口,因此提供国际化支持。
- 资源访问,比如URL和文件。
- 事件机制,可向注册为监听器的Bean发送事件。
- 载入多个配置文件。
- 以声明式的方式启动、并创建Spring容器。
6 项目中如何引入Spring框架
资源下载
- 下载软件包官网https://spring.io/
- 云盘4.1.6版本下载地址http://pan.baidu.com/s/1dEZ444h
6.1 Hello spring
6.1.1 导入相关jar包
spring-aop-4.1.6.RELEASE.jar
spring-aspects-4.1.6.RELEASE.jar
spring-beans-4.1.6.RELEASE.jar
spring-context-4.1.6.RELEASE.jar
spring-context-support-4.1.6.RELEASE.jar
spring-core-4.1.6.RELEASE.jar
spring-expression-4.1.6.RELEASE.jar
spring-jdbc-4.1.6.RELEASE.jar
spring-orm-4.1.6.RELEASE.jar
spring-tx-4.1.6.RELEASE.jar
spring-web-4.1.6.RELEASE.jar
spring-webmvc-4.1.6.RELEASE.jar
commons-logging-1.1.3.jar(struts软件包里)
6.1.2HelloSpring.java
public class HelloSpring { private String name; public void setName(String name) { this.name = name; } public void show(){ System.out.println("hello:"+name); } }
6.1.3 Beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="hello" class="com.silvan.pojo.HelloSpring"> <property name="name" value="spring"></property> </bean> </beans>
6.1.4 Test.java
public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); HelloSpring hello = (HelloSpring)context.getBean("hello"); hello.show(); } }
思考:
helloSpring对象是由谁创建的?Spring容器
helloSpring对象属性是谁设置的,怎么设置的?Spring容器,通过set方法后面的名字与property标签name的属性值进行匹配的。
这个过程就叫做控制反转。
总结:以前对象是由程序本身来创建,使用spring后,程序变为被动接受spring创建好的对象。
控制反转还有另外一种说法------依赖注入
结果就是主动去做的事情变为被动接收。
主动跟被动有什么区别:过程更自动化,更省事。
对ioc的详细解释:http://www.cnblogs.com/xdp-gacl/p/3707631.html