一、Spring概述:
1.什么是Spring?
Spring是分层的JavaSE/EE应用full-stack(一站式)轻量级开源框架,以IoC(Inverse Of Control:控制反转)和AoP(Aspect Oriented Programing,面向切面编程)为内核,提供了展现层SpringMVC和持久层Spring JDBC以及业务层事务管理等众多的企业级应用技术,还能提供开源世界众多著名的第三方框架和类库,逐渐成为使用最多的JavaEE企业级应用开源框架。
2.Spring框架的优点:
(1)非侵入式设计:Spring是一种非侵入式(non-invasion框架),它可以使用用程序代码对框架的依赖最小化。
(2)方便解耦、简化开发:Spring是一个大工厂,可以将所有的对象的创建和依赖关系的维护工作都交给Spring容器进行管理,大大降低了组件之间的耦合性。
(3)支持AOP:Spring框架提供了对AOP的支持,允许将一些通用的任务,如安全、事务、日志等进行集中式的处理,从而提高了程序的复用性。
(4)支持声明式事务的处理:只需要配置就可以完成对事务的管理,而无需手动编程
(5)方便程序的测试:Spring程序提供了对Junit4的支持,可以通过注解的方式方便地测试Spring程序。
(6)方便集成各种优秀的框架:Spring提供了对各种优秀框架的直接支持。
(7)降低了JavaEE API的使用难度:Spring对JavaEE API(如JDBC JavaMail、远程调用等)进行了薄薄的封装,使得API的使用难度大大降低。
3.Spring的体系结构
如上图所示,该图中包含了Spring框架的所有模块,接下来将对体系结构中的主要模块进行简单的介绍:
(1)Core Container(核心容器)
Spring的核心容器是其他模块建立的基础,主要包含Beans模块、Core模块、Context模块、Context-support模块和SpEL模块。具体的介绍如下:
Beans模块:提供了BeanFactory,是工厂模式的经典体现,Spring将管理的对象称为Bean。
Core核心模块:提供了Spring框架的基本组成部分,包括IoC和DI功能
Context上下文模块:建立在Core和Beans模块的基础之上,它是访问定义和配置的任何对象的媒介。其中ApplicationContext接口是上下文模块的焦点。
Context-support模块:提供了对第三方库嵌入Spring应用的集成支持,比如缓存,邮件服务、任务调度和模板引擎
SpEL模块:是Spring3.0后新增的模块,提供了Spring Expression Language支持,是运行时查询和操作对象图的强大表达式语言。
(2)Data Access/Integration(数据访问/集成)
数据范文/集成层包括JDBC、ORM、OXM和Transaction模块,具体介绍如下。
JDBC模块:提供了一个JDBC的抽象层,大幅度地减少了在开发过程中对数据库操作的编码。
ORM模块:对流行的对象关系映射API,包括JPA、JDO和Hibernate提供了集成层的支持
OXM模块:提供了一个支持对象/XML映射的抽象层实现,如JAXB、Castor、XMLBeans、JiBX和XStream。
JMS模块:指Java消息传递服务,包含使用和产生信息的特性
Transaction事务模块:支持对实现特殊接口以及所有POJO类的编程和声明式的事务管理。
(3)Web
Spring的Web层包括WebSocket、Servelet、Web和Portlet模块,具体介绍如下:
WebSocket模块:提供了WebSocket和SocketJS的实现,以及Stomp的支持。
Servlet模块:也称为Spring-webmvc模块,包含了Spring的模型-视图-控制器(MVC)和REST Web Service实现的Web应用程序。
Web模块:提供了基本的Web开发集成特性,如:文件上传功能、使用Servlet监听器来初始化IoC容器以及Web应用上下文
Portlet模块:提供了在Portlet环境中使用MVC实现,类似Servlet模块的功能。
(4)其他模块:Spring的其他模块还有AOP、Aspects、Instrumenttation以及Test模块,具体的介绍如下:
AOP模块:提供了面向切面编程的实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。
Aspects模块:提供了与AspectJ的集成功能,AspectJ是一个功能强大且成熟的面向切面编程(AOP)框架。
Instrumentation模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用
Messaging模块:提供可对消息传递体系结构和协议的支持
Test模块:提供了对单元测试和集成测试的支持。
二、Spring的核心容器
Spring框架的主要功能是通过其核心容器来实现的,Spring框架提供了两种核心容器,分别是BeanFactory和ApplicationContext
1.BeanFactory。BeanFactory由org.springframework.beans.factory.BeanFactory接口定义,是基础类型的IoC容器,提供了完整的IoC服务支持,简单来说BeanFactory就是一个管理Bean的工厂,主要负责初始化各种Bean,并调用他们的生命周期方法。BeanFactory接口提供了几个实现类,其中最常用的是org.springframework.beans.factory.xml.XmlBeanFactory,会根据XML配置文件的定义来装配Bean,
2.ApplicationContext:是BeanFactory的子接口,被称为应用上下文,是另一种Spring的核心容器。由org.springframework.context.applicationContext接口定义,不仅包含了BeanFactory的所有功能,还添加了对国际化、资源访问、事件传播等方面的支持。创建ApplicationContext接口实例,通常有两种方式,具体如下:
(1)通过ClassPathApplicationContext创建,ClassPathXmlApplicationContext会从类路径classpath中寻找指定的xml配置文件,找到并装在完成ApplicationContext的实例化工作,其使用的语法如下:
ApplicationContext applicationContext = new ClassPathApplicationContext(String location);//configLocation参数用于指定Spring配置文件的名称位置,如果其值为applicationContext.xml,则Spring会去类路径中查找//名称为applicationContext.xml的配置文件
(2)通过FileSystemXmlApplicationContext创建。FileSystemXmlApplicationContext会从指定的文件系统路径中寻找指定的XML配置文件,并装载完成ApplicationContext的实例化工作,其使用的语法如下:
ApplicationContext applicationContext =new FileSystemXmlApplicationContext(String location);
与ClassPathXmlApplicationContext有所不同的是,在读取Spring配置文件的时候,FileSystemXmlApplicationContext不再从类路径中读取配置文件,而是通过参数指定配置文件的位置。如果在参数中写的不是绝对路径,那么在方法调用的时候,会默认用绝对路径来查找。但是采用绝对路径的方式会导致程序的灵活性变差,所以这个方法一般不推荐使用。在使用Spring框架的时候,可以通过实例化其中任意一个类来创建ApplicationContext容器。通常在java项目中,会通过ClassPathXmlApplicationContext类来实例化ApplicationContext容器的方式,而在Web项目中,ApplicationContext容器的实例化工作会由Web服务器来完成。在Spring容器创建之后,就可以获取Spring容器中的Bean。Spring获取Bean的实例通常采用以下两种方法:Object getBean(String name):根据容器中的Bean的id或者name来获取指定的Bean,获取之后需要进行强制类型转换。
(3)BeanFactory和ApplicationContext两种容器都是通过XML配置文件加载Bean的。两者的主要区别在于:如果Bean的某个属性没有注入,使用BeanFactory加载之后,在第一次调用getBean()方法的时候会抛出异常,而ApplicationContext则在初始化的时候自检,这样有利于检查所依赖的属性是否注入。在实际开发过程中,通常都优先选择使用ApplicationContext,而在只有系统资源比较少的时候,才会考虑BeanFactory.
三、接下来我们通过案例的方式来演示Spring框架的使用
(1)首先创建一个Maven工程,导入jar包
(2)在src目录下,创建一个com.nju.ioc的包,并在包中创建UserDao接口,然后在接口中创建一个say()方法。
(3)在com.nju.ioc包下,创建UserDao接口的实现类UserDaoImpl,该类需要实现接口中的say()方法,并在方法中编写一条输出语句。
(4)在src目录下,创建一个Spring配置文件applicationContext.xml,并在配置文件中创建一个id为userDao的Bean,如下图所示。下图中2-5行是Spring的约束配置,第六行代码表示在Spring容器中创建一个id为userDao的Bean实例,其中class属性用于指定需要实例化Bean的类。(在实际开发过程中,配置文件一般都会命名为applicationContext.xml或者beans.xml)
(5)在com.nju.ioc包下,创建测试类TestIOC,并在类中编写main()方法,在main方法中,需要初始化Spring容器,并加载配置文件,然后通过Spring容器获取userDao实例(即Java对象),最后调用实例的say()方法。
(6)从控制台输出的结果可以看出如下图所示
从上图中可以看出,控制台已经成功输出了UserDaoImpl类的输出语句。在main方法中并没有通过new关键字来创建UserDao接口的实现类对象,而是通过Spring容器来获取实现类的对象,这就是Spring IoC容器的工作机制。
四、依赖注入
1.依赖注入的概念
(1)依赖注入(Dependency Injection,简称DI)与控制反转含义相同,只不过这两个称呼是从两个角度来描述同一个概念的。当Java对象需要调用另一个Java对象的时候,在传统的模式下,调用者通常会采用new 被调用对象的代码的方式来进行创建对象,但是这种方式会增加调用者与被调用者之间的耦合性,不利于后期项目的升级与维护,而在使用Spring框架之后,对象的实例不再由Spring容器来进行创建,Spring容器会负责控制程序之间的关系,而不是由调用者的程序直接的进行控制。这样控制器应用代码转到了Spring控制器,控制权发生了反转,这就是Spring的控制反转。
(2)从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了依赖实例,这就是Spring的依赖注入。
2.依赖注入的实现方式
(1)依赖注入的的作用就是在使用Spring框架创建对象的时候,动态的将其依赖的对象注入到Bean组件中,其实现的方式通常有两种,一种是通过setter()方法进行注入,另一种方式是通过构造方法进行注入。具体的介绍方法如下。
属性的setter的注入:指IoC容器使用setter方法注入被依赖的实例。通过调用午餐构造器或者无参静态工厂方法实例化Bean之后,调用该Bean的setter方法,即可实现基于setter方法的依赖注入。其代码实现的方式如下:
代码:在com.nju.ioc包中,创建接口UserService,在接口中编写一个say()方法,如下所示:
(2)在com.nju.ioc包中,创建UserService接口的实现类UserServiceImpl,在类中声明userDao属性,并添加属性的setter方法,如下图所示:
(3)在配置文件applicationContext.xml中创建一个id为userService的Bean,该Bean用于实例化UserServiceImpl类的信息,并将userDao的实例注入到userService中,
(4)编写TestDI,来对程序进行测试。
(5)执行结果如下图所示:
从上图中可以看出,使用Spring容器通过UserService实现类中的say()方法,调用了UserDao实现类的中的say()方法,并输出了结果,这就是Spring容器属性setter注入的方式,也是实际开发中最常用的方式。