您的位置:首页 > 编程语言 > Java开发

1、spring简介

2016-06-06 12:00 525 查看

1. Spring简介

Spring是于2003年兴起的一个轻量级(对应于ejb)的Java 开发框架,由Rod
Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转IoC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE
full-stack(一站式) 轻量级开源框架。他的核心是ioc(Inversion of Control)/di(dependency injection),即通过配置文件的方式来完成java类依赖关系的自动装配。将在下一节课进行学习,本节课主要了解spring中一些常用的接口和spring的配置文件说明并完成一个helloworld级别的spring程序。

2. Spring 框架概述

Spring框架包含许多特性,并被很好地组织在下图所示的七个模块中。本节将依次介绍每个模块。

3. 框架特性

Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
轻量——轻量是针对重量级容器(EJBjndi)来说的。从大小与开销两方面而言完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。
Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
控制反转(di)——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

面向切面(aop)——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
容器(Context)——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。Spring有两种不同的容器
l Bean工厂(org.springframework.beans.factory.BeanFactory)
最简单的容器(是Spring基本的IOC容器),提供了基础的依赖注入支持。而BeanFactory容器在Bean的Scope为prototypeo时实例化后并不会自动实例化Bean,只有当Bean被使用时BeanFactory容器才会对该Bean进行实例化与依赖关系的装配。
l ApplicationContext应用上下文(org.springframework.context.ApplicationContext)
建立在Bean工厂基础之上,提供了系统构架服务 , ApplicationContext容器实例化后会自动对所有的单实例Bean进行实例化与依赖关系的装配,使之处于待用状态,ApplicationContext容器还可以提供其它的一些功能比如:jms等
框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

4. Spring jar包说明 :

Myeclipse10.0自带spring最高版本3.0版本,
spring目前已经托管到github可从hithub上下载到最新版本的spring.

Spring的安装比较简单,直接将下载的jar包导入到web工程的lib目录即可。

l spring-core.jar:包含SpringIOC和全局使用的类,
ApplicationContext接口在此包中,spring开发必须的包

l spring-beans.jar:spring的Bean工厂的包,包含BeanFactory接口spring开发必须的包

l spring-context.jar:提供IOC高级功能,JNDI、EJB的支持等spring开发必须的包

l spring-aop.jar:Spring的AOP框架,如果需要使用spring的aop特性需要引入该包,比如使用声明式事务管理等。

l spring-dao.jar:提供了对数据库的访问抽象,提供了对JDBC和数据库事务的支持

l spring-orm.jar:提供了对Hibernate,
myBATIS等持久层框架的支持

l spring-struts.jar:与struts整合开发时必须的包

l spring-mybatis.jar:与mybatis整合开发时必须的包

l spring-expression:Spring3.0引入一个全新的功能,表达式语言(EL)简称SpELspring表达式支持的包,因为spring的配置文件使用了表达式所以这个包是spring3.0以上版本开发必须的包spring3.0以上版本开发必须的包

l spring-web.jar:提供了对web的支持,如果你的项目是web程序那么必须要引入此包,org.springframework.web.context.ContextLoaderListener就在此包中

l spring-webmvc.jar:Spring自己的Web框架,如果使用spring与其它前台框架(struts2)进行集成开发不必引入此包

l spring-test.jar:提供了nunit进行测试的包junit

5. Spring常用接口及实现类:

ApplicationContext 接口:

l 在ApplicationContext接口的众多实现类中,有3个是我们经常用到的(见表1-1),并且使用这3个实现类也基本能满足我们Java EE应用开发中的绝大部分需求。
表1-1 ApplicationContext接口的常用实现类介绍

类 名 称
功 能 描 述
ClassPathXmlApplicationContext
类路径ClassPath中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作。
例如:
//装载单个配置文件实例化ApplicationContext容器
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
//装载多个配置文件实例化ApplicationContext容器
String[] configs = {"bean1.xml","bean2.xml","bean3.xml"};
ApplicationContext cxt = new ClassPathXmlApplicationContext(configs);
注意】此处是已项目的类路径为根(src目录或者说是classes目录),上例中的所有的.xml文件都应该在src目录下。【常用】
FileSystemXmlApplicationContext
从指定的文件系统路径中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作。
例如:
//装载单个配置文件实例化ApplicationContext容器
ApplicationContext cxt = new FileSystemXMLApplicationContext("beans.xml");
//装载多个配置文件实例化ApplicationContext容器
String[] configs = {"beans1.xml","c:/beans2.xml"};
ApplicationContext cxt = new FileSystemXmlApplicationContext(configs);
【注意】:此处是以文件系统为路径,如果使用绝对路径那么会在磁盘的对应位置读取配置文件,如果以相对路径会在项目的根目录下读取,
图中的配置文件可通过:new FileSystemXmlApplicationContext(“ApplicationContext.xml”);读取【不常用】
XmlWebApplicationContext
从Web应用中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作。这是为Web工程量身定制的,使用
WebApplicationContextUtils类的getRequiredWebApplicationContext方法
可在JSP与Servlet中取得IoC容器的引用,就可以得到容器中所有的bean【在servlet中得到bean工厂时常用】
这些实现类的主要区别就是装载Spring配置文件实例化ApplicationContext容器的方式不同,在ApplicationContext实例化后,同样通过getBean方法从ApplicationContext容器中获取装配好的Bean实例以供使用。
与BeanFactory不同的是,ApplicationContext容器实例化后会自动对所有的单实例Bean进行实例化与依赖关系的装配,使之处于待用状态。而BeanFactory容器实例化后并不会自动实例化Bean,只有当Bean被使用时BeanFactory容器才会对该Bean进行实例化与依赖关系的装配。
在Java项目中通过ClassPathXmlApplicationContext类手动实例化ApplicationContext容器通常是不二之选。但对于Web项目就不行了,Web项目的启动是由相应的Web服务器负责的,因此,在Web项目中ApplicationContext容器的实例化工作最好交给Web服务器来完成。
【注意】:这里读取配置文件的方式只用于开发java程序或者是测试的时候,在开发web应用程序的时配置文件是由spring来自动读取的。读取的方式在开发web应用程序的时候做介绍

6. web应用使用spring

Spring为此提供了两种解决方案,一种是基于ContextLoaderListener实现的(此方案只适用于Servlet2.4及以上规范的Servlet容器)。例如,在web.xml中加入如下代码:

<!-- 指定Spring的配置文件,多个配置文件以逗号分隔 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!-- 指定以Listener方式启动Spring容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


【注意这里的配置文件在WEB-INF目录下】

另外一种方案则是基于ContextLoaderServlet实现的。例如,在web.xml中加入如下代码:
<!-- 指定Spring的配置文件,多个配置文件以逗号分隔 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config/applicationContext.xml</param-value>
</context-param>
<!-- 指定以Servlet方式启动Spring容器 -->
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

从servlet容器启动时加载组件的顺序来看,Listener组件是优先于Servlet组件的。基于Servlet方式的加载方案主要是为了兼容Servlet2.3及以下规范的Servlet容器。以Tomcat为例,Tomcat5.x都已经支持Servlet2.4规范了,因此,基于Listener方式启动Spring容器是目前的主流选择。[1]
对于application.xml配置文件会在以后章节进行详细说明。

7. bean容器(ioc容器)

Spring的所有对象都是通过bean容器来进行管理的。spring在启动的时候会读取配置文件来实例化应用中的所有对象,并进行对象的依赖注入【注意如果你的Bean需要由spring进行管理,一定不要通过代码来实例化(不要在代码中通过new关键字实例化)】,spring的bean是由xml文件进行配置的,spring的bean配置主要使用bean、property

Bean:

spring中的对象是通过bean节点来进行配置的,表示一个类下表为bean节点的主要属性【注意其中最常用的属性是id、class/scope】

属性名

是否必须

属性值

默认值

属性描述

Id



Bean的唯一标识名。它必须是合法的XML ID,在整个XML文档中唯一用来定义bean的唯一id,如果其它类中依赖这个类,可以通过id进行引用

name





用来为id创建一个或多个别名。它可以是任意的字母符合。多个别名之间用逗号或空格分开【注意别名主要用于其它一些bean的属性当中,不建议使用】

class



类的全限定名



Spring根据class属性通过反射机制来实例化对象只有子类Bean不用定义该属性【注意,不建议使用子类的方式来定义bean,最好直接将class定义为类的全限定类名】

scope



Singleton:单例

Prototype:不是单例,每次getBean都是一个新的实例

Request:用于web开发,每一次请求中是同一个实例

Session:每次会话中都是同一个实例 request和session不常用

singleton

如果类中的全局变量会有线程安全方面的问题,就可以使用prototype类型

Abstract



True:

false

false

表示是抽象类applicationContext预实例化时忽略所有的抽象Bean的定义一般与parent属性一起使用

parent



Bean标签中abstract属性为true的Bean的ID

【不常用】

Lazy-init



True

false

false

值为true表示延迟加载,也就是IoC容器将第一次被用到时才开始实例化【注意每次通过property标签引用bean的时候spring内部都会调用一次getBean方法】

autowire



byName

bytype

constructor

autodetect

no

byName

byName 根据Bean定义时的“id"属性上指定的别名与Setter名称是否一致进行自动装配

byType 根据PoJo的setXXX()方法所接受的类型判断bean定义文件是否定义有类似的类型对象进行自动装配

constructor Spring容器比对容器中的Bean实例类型及相关的构造方法上的参数类型是否符合进行自动装配

autodetect 先进行constructor自动装配,若缺省,则进行byType自动装配

no不进行自动装配【不常用】

depends-on



Beanid



若A depends-on B 意思是实例化A之前必须先实例化B,但A不需要持有B的实例【不常用】

dependency-check



simple

objects

none

none

simple 只检查简单的属性是否完成依赖关系

objects 检查对象类型的属性是否完成依赖关系

all检查全部的属性是否完成依赖关系

none默认值,表示不检查依赖性【不常用】

factory-bean







通过实例工厂方法创建bean,class属性必须为空,factory-bean属性必须指定一个bean的名字,这个bean一定要在当前的bean工厂或者父bean工厂中,并包含工厂方法。而工厂方法本身通过factory-method属性设置。【不常用】

factory-method







定义工厂方法,若是class属性指向工厂类,该工厂类包含的工厂方法须是static【不常用】

Property:

Property标签主要用来对类的依赖对象进行注入,常用的属性包括name,ref,class

属性名

是否必须

属性值

默认值

描述

name







对应java类中全局变量的变量名称。【必须有set方法】

Class







全限定类名

Ref







对应spring配置文件中bean的id,表示会将id对应的bean注入。

8. 第一个spring 程序:

使用spring的步骤:

1、 导入jar包,

2、 写一个xml配置文件ApplicationContext.xml

下面我们通过一个spring程序来实现java对象的注入,大家回想一下在之间的java学习当中如果一个类需要使用另一个类,我们是怎么做的,比方说userServlet如果要访问数据库,那么他里面就可能会需要使用一个类似于名字为userDao的对象。那么在userServlet里面是不是需要类似下面这样的一行代码:

UserDao userDao= new UserDao();

这样的关系我们把他称为依赖,就是说我们的userServlet类在进行逻辑运算的过程中依赖于userDao访问数据库的功能。大家想一下这样做有没有什么弊端。如果说我们换数据库了,或者是不使用数据库了,而是从远程服务器上得到userServlet中需要的资源比如用户信息等。那么我们是不是需要去改动userservlet中的代码,而我们的程序上线后往往都是打成jar文件了,这样改动起来就会比较麻烦,下面我们看看spring是怎么处理这种关系的。

程序说明:userService类依赖userDao,在userService的sayHello方法中调用userDao的getUser(Stringid)方法得到user对象。然后输出XX用户,,你好!程序比较简单,我们主要从这个小小的程序当中体会一下spring他到底干了些什么,这么干有什么用,怎样使用spring来构建一个最基本的应用。

程序文件清单

Java文件:UserDao,UserService,User

Xml:applicationcontext.xml(spring默认的配置文件)

测试文件:test.java

Usedao:

package com.spring.dao;

import com.spring.pojo.User;

public class UserDao {
public UserDao(){
System.out.println("userDao");
}

public void init(){
System.out.println("init()");

}
public User getUserByid(String id){
User user = new User();
user.setPassword("pwd");
user.setUsername("itjob");
return user;
}
public void destroy(){
System.out.println("destroy");
}
}
userService:

package com.spring.service;
import com.spring.dao.UserDao;
import com.spring.pojo.User;
public class UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void sayHello(){
User user = userDao.getUserByid("a");
System.out.println(user.getUsername() + " 用户,hello!");
}
}
spring.xml

<bean id="userDao" lazy-init="true" class="com.spring.dao.UserDao" ></bean>
<!—定义userService-->
<bean id="userService" class="com.spring.service.UserService">
<!-- 注意这里的name 必须要和UserService类中的userDao的 名称一致如下,
private UserDao userDao;
并且必须有setUserDao方法:
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
-->
<property name="userDao" ref="userDao"></property>
</bean>
测试类

public static void main(String[] args) {
//通过classPathXmlApplication 类来实例化spring的上下文对象
ApplicationContext context = new  ClassPathXmlApplicationContext("applicationContext.xml");
//从上下文容器中得到userService
/**
* 注意 这里得到的userService是经过spring 注入了userDao的userService实例
* 因为getBean方法得到的是一个Object类型的对象,所以需要进行强制类型转换
*/
UserService userService = (UserService)context.getBean("userService");
userService.sayHello();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: