spring框架(一)
Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
正是因为spring框架性质是属于容器性质的,容器中装什么对象就有什么功能,它在Java 开发中充当一个管家的角色,用来管理对象,但不止于管理对象。所以spring是一个一站式开源框架,它不仅不排斥其他框架,还能帮其他框架管理对象。
spring框架特征
控制反转——Spring通过一种称作控制反转(IoC)的技术促进了低耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
IOC:Inverse Of Control 也就是控制反转,spring将我们创建对象的方式反转了。
在使用spring之前,对象的创建由开发人员自己维护,包括依赖关系也是自己注入,使用spring之后,对象的创建以及依赖关系可以由spring完成创建,以及注入。所以,控制反转,就是反转了对象的创建方式,从我们自己创建反转给了程序(spring)。
DI:Denpendency Injection 依赖注入,实现IOC思想需要DI做支持,spring提供的注入方式常见的有:set方法注入,构造方法注入,字段注入,注入类型:值类型注入(八大基本数据类型),引用类型注入(将依赖对象注入)
面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
spring入门
既然spring是个管理对象的管家,那么如何把对象交给spring管理?先做一个演示
1.创建一个User类
2.书写配置注册对象到容器,配置文件名任意,建议使用applicationContext.xml,位置任意,建议放在src下,编写xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<bean name="user" class="cn.itcast.bean.User" ></bean>
</beans>
代码测试
public class Demo {
@Test
public void fun1(){
//1 创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
/*//2 向容器"要"user对象
User u = (User) ac.getBean("user");
//3 打印user对象
System.out.println(u);*/
}
}
这样,程序在加载了spring的配置文件applicationContext.xml后,自动new了user对象,我们向spring容器索取user对象引用,成功获取并打印user对象。
applicationContext与BeanFactory的区别
Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类。事实上,Spring提供了两种不同的容器:一种是最基本的BeanFactory,另一种是扩展的ApplicationContext。BeanFactory 仅提供了最基本的依赖注入支持,而 ApplicationContext 则扩展了BeanFactory ,提供了更多的额外功能。二者对Bean的初始化也有很大区别。BeanFactory当需要调用时读取配置信息,生成某个类的实例。如果读入的Bean配置正确,则其他的配置中有错误也不会影响程序的运行。而ApplicationContext 在初始化时就把 xml 的配置信息读入内存,对 XML 文件进行检验,如果配置文件没有错误,就创建所有的Bean ,直接为应用程序服务。相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
ApplicationContext的三个实现类:
a、 ClassPathXmlApplication:把上下文文件当成类路径资源,开发最常用
b、 FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息
c、 XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息
spring配置详解
bean元素
使用该元素描述需要spring容器管理的对象
class属性:被管理对象的完整类名.
name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象. 可以重复.可以使用特殊字符.
id属性: 与name属性一模一样. 名称不可重复.不能使用特殊字符.
name属性是由于struts等常用/action来命名,为了保持规范,不破坏id的规则(不使用特殊符号如/),spring特地设计的属性,我们一般使用name属性.
Bean元素进阶
scope属性
singleton(默认值):单例对象.被标识为单例的对象在spring容器中只会存在一个实例
prototype:多例原型.被标识为多例的对象,每次再获得才会创建.每次创建都是新的对象.整合struts2时,ActionBean必须配置为多例的.
request:web环境下.对象与request生命周期一致.
session:web环境下,对象与session生命周期一致.
生命周期属性
init-method:配置一个方法作为生命周期初始化方法.spring会在对象创建之后立即调用.
destory-method:配置一个方法作为生命周期的销毁方法.spring容器在关闭并销毁所有容器中的对象之前调用.
<bean name="user" class="cn.itcast.bean.User"
init-method="init" destroy-method="destory" ></bean>
spring创建对象的方式
1. 空参构造方式
<bean name="user" class="cn.itcast.bean.User"></bean>
2. 静态工厂
使用静态工厂有许多好处,这里先不提,先来看看如何再spring中使用静态工厂创建对象。
创建一个UserFactory类,提供静态方法createUser
public class UserFactory {
public static User createUser (){
System.out.println("静态工厂创建User");
return new User();
}
}
<bean name="user2"
class="cn.itcast.b_create.UserFactory"
factory-method="createUser" ></bean>
这样,spring会调用UserFactory的createUser方法创建名为user2的对象.放入容器
3. 实例工厂
在刚才的UserFactory 类中添加如下方法:
public User createUser2(){
System.out.println("实例工厂创建User");
return new User();
}
使用实例工厂创建对象,首先要有工厂实例,需要先创建工厂对象,然后再spring中使用如下配置,装配工厂对象和指定工厂方法。
<bean name="user3"
factory-bean="userFactory"
factory-method="createUser2" ></bean>
<bean name="userFactory"
class="cn.itcast.b_create.UserFactory" ></bean>
spring的分模块配置
如果工厂较大,spring就需要进行分模块配置,不然配置信息就显得杂乱,那么就可以在主配置中使用如下配置导入其他的spring配置文件
<!-- 导入其他spring配置文件 -->
<import resource=" applicationContext-service.xml"/>
spring的属性注入方式
set方法注入
使用property元素作为bean元素的子元素,可以为bean注入属性
property的name元素对应对象的属性名,value为注入的字段值(只支持八大类型及string),
注入引用类型时,可以使用ref属性,其中,被注入的对象需先配置到spring容器中,如下所示
<!-- set方式注入: -->
<bean name="user" class="cn.itcast.bean.User" >
<!--值类型注入: 为User对象中名为name的属性注入tom作为值 -->
<property name="name" value="tom" ></property>
<property name="age" value="18" ></property>
<!-- 引用类型注入: 为car属性注入下方配置的car对象 -->
<property name="car" ref="car" ></property>
</bean>
<!-- 将car对象配置到容器中 -->
<bean name="car" class="cn.itcast.bean.Car" >
<property name="name" value="兰博基尼" ></property>
<property name="color" value="黄色" ></property>
</bean>
构造函数注入
使用构造函数注入时,我们提供constructor-arg来完成属性注入。
其中,name,index,type作为辨别参数的三维,灵活运用这三个属性可以辨别出唯一指定的构造函数及参数。此方法较set方法比较较为复杂,建议使用set方法注入
<bean name="user2" class="cn.itcast.bean.User" >
<!-- name属性: 构造函数的参数名 -->
<!-- index属性: 构造函数的参数索引 -->
<!-- type属性: 构造函数的参数类型-->
<constructor-arg name="name" index="0" type="java.lang.Integer" value="999" ></constructor-arg>
<constructor-arg name="car" ref="car" index="1" ></constructor-arg>
</bean>
p名称空间注入
此方法为spring新增的注入方式,目前还未被广泛接受,但是学习了P名称空间注入有助于提高开发效率。
p名称空间注入, 一般是使用set方法注入属性,使用P名称空间注入,需先导入P名称空间 xmlns:p=http://www.springframework.org/schema/p
使用p:属性完成注入
|-值类型: p:属性名="值"
|-对象类型: p:属性名-ref="bean名称"
<bean name="user3" class="cn.itcast.bean.User" p:name="jack" p:age="20" p:car-ref="car" >
</bean>
复杂类型注入
先创建一个演示类CollectionBean
public class CollectionBean {
private Object[] arr;//数组类型注入
private List list;//list/set 类型注入
private Map map;//map类型注入
private Properties prop;//properties类型注入
//省略set get方法 }
数组注入
<property name="arr">
<array>
<value>tom</value>
<value>jerry</value>
<ref bean="user4" />
</array>
</property>
List注入
<property name="list" >
<list>
<value>jack</value>
<value>rose</value>
<ref bean="user3" />
</list>
</property>
Map注入
<property name="map" >
<map>
<entry key="url" value="jdbc:mysql:///crm" ></entry>
<entry key="user" value-ref="user4" ></entry>
<entry key-ref="user3" value-ref="user2" ></entry>
</map>
</property>
prorerties注入
<property name="prop" >
<props>
<prop key="driverClass">com.jdbc.mysql.Driver</prop>
<prop key="userName">root</prop>
<prop key="password">1234</prop>
</props>
</property>