概述
简介
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,它是为了解决企业应用开发的复杂性而创建的。
框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring 使用基本的 JavaBean来完成以前只可能由 EJB 完成的事情。然而,Spring 的用途不仅限于服务器端的开发。
从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 的核心是控制反转(IoC)和面向切面(AOP)。简单来说,Spring 是一个分层的 JavaSE/EEfull-stack(一站式) 轻量级开源框架。
优势
- 方便解耦,简化开发
Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护,交给 Spring 管理 -
AOP 编程的支持
Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能 -
声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程 -
方便程序的测试
Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序 -
方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持 -
降低 JavaEE API 的使用难度
Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装,
使这些 API 应用难度大大降低
环境搭建及测试
下载包
官网:http://spring.io/
下载地址:http://repo.springsource.org/libs-release-local/org/springframework/spring
解压:(Spring 目录结构:)
* docs :API 和开发规范.
* libs :jar 包和源码.
* schema :约束.
创建Web项目,引入Jar包
可以看到,Spring核心容器的组件包括Beans、Core、Context、Expression Language。
分别对应spring-beans.jar、spring-core.jar、spring-context.jar、spring-expression.jar。
这四个Jar包是Spring最基础的Jar包。
Spring使用的是apache的日志包,所以还须引入com.springsource.org.apache.commons.logging.jar。
部分老版本还要导入com.springsource.org.apache.log4j.jar。
配置文件
编写实体类
先写一个实体类User.java。
package cn.itcast.bean;
public class User {
private String name;
private Integer age;
public User() {
System.out.println("User对象空参构造方法!!!!");
}
//get、set、toString方法省略
}
书写配置对象到容器
新建一个xml文件,
配置文件名任意(建议:applicationContext.xml)
配置文件位置任意(建议放到src下)
导入约束:
Preferences->XML Catelog->File System->找到spring的schema/beans/XXXX(最新版).xsd->打开->Key type选择Schema location->把约束文件名(XXXX.xsd)粘贴到Key输入框的最后面->OK->
输入beans元素->切换到设计视图->在beans元素上点击右键->Edit Namespaces->Add...->选中xsi->OK->Add...->Specify New Namespace->Browse->Select XML Catelog entry->找到刚才导入的XXX.xsd->OK->把Location Hint的路径(去掉文件名:/XXX.xsd)粘贴到Namespace Name中->OK。
如果在beans中输入<有提示,就说明约束导入成功了。
之后将需要Spring管理的对象放在beans元素中,用bean元素描述就可以了。
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Spring 的入门案例================ -->
<bean id="userDao" class="cn.itcast.bean.User"></bean>
</beans>
编写测试代码
Demo.java
package cn.itcast.c_injection;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.bean.User;
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);
}
}
思想
IOC
Inversion of Control 控制反转. 指的是 对象的创建权反转(交给)给 Spring.由程序员自己创建反转给了Spring创建。作用是实现了程序的解耦合.
DI
Dependency Injection 依赖注入.实现IOC思想需要有DI做支持,Spring 创建这个类的过程中,Spring 将类的依赖的属性设置进去.
注入方式:
1. set方法注入
2. 构造方法注入
3. 字段注入
注入方式:
1. 值类型注入
2. 引用类型注入
工厂(容器)
BeanFactory :是在 getBean 的时候才会生成类的实例.
ApplicationContext :在加载 applicationContext.xml(容器启动)时候就会创建.
ApplicationContext:
每次容器启动时就会创建容器中配置的所有对象.并提供更多功能
ApplicatioContext 接口有两个实现类:
* ClassPathXmlApplicationContext :加载类路径下 Spring 的配置文件.
* FileSystemXmlApplicationContext :加载本地磁盘下 Spring 的配置文件.
BeanFactory(过时):
spring原始接口.针对原始接口的实现类功能较为单一
BeanFactory接口实现类的容器.特点是每次在获得对象时才会创建对象
总结
web开发中,使用applicationContext. 在资源匮乏的环境可以使用BeanFactory.
配置详解
<?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 ">
<!-- 将User对象交给spring容器管理 -->
<!-- Bean元素:使用该元素描述需要spring容器管理的对象-->
<bean name="user" class="cn.itcast.bean.User"></bean>
<import resource="cn/itcast/b_create/otherContext.xml"/>
</beans>
import元素
可以使用import元素来引入其他配置文件,实现分模块控制。
<import resource="cn/itcast/b_create/otherContext.xml"/>
bean元素
属性
class属性
被管理对象的完整类名
name属性和id属性
- name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象.
可以重复.可以使用特殊字符. -
id属性: 与name属性一模一样.
名称不可重复.不能使用特殊字符.
结论: 尽量使用name属性.
scope属性
指定bean的作用范围,其取值有以下几个:
* singleton
单例对象.被标识为单例的对象在spring容器中只会存在一个实例。
- prototype
多例原型.被标识为多例的对象,每次再获得才会创建.每次创建都是新的对象.
整合struts2时,ActionBean必须配置为多例的. -
request
web环境下.对象与request生命周期一致. -
session
web环境下,对象与session生命周期一致. -
globalSession
WEB 项目中,应用在 Porlet 环境.如果没有 Porlet 环境那么 globalSession 相当于 session.
init-method
配置一个方法作为生命周期初始化方法.spring会在对象创建之后立即调用.
destory-method
配置一个方法作为生命周期的销毁方法.spring容器在关闭并销毁所有容器中的对象之前调用.
创建对象的方式
空参构造方式
<bean name="user" class="cn.itcast.bean.User" ></bean>
静态工厂
package cn.itcast.b_create;
import cn.itcast.bean.User;
public class UserFactory {
public static User createUser(){
System.out.println("静态工厂创建User");
return new User();
}
}
<bean name="user" class="cn.itcast.bean.UserFactory" factory-method="createUser"></bean>
实例工厂
package cn.itcast.b_create;
import cn.itcast.bean.User;
public class UserFactory {
public User createUser(){
System.out.println("静态工厂创建User");
return new User();
}
}
<bean name="user" factory-bean="userFactory" factory-method="createUser"></bean>
<bean name="userFactory" class="cn.itcast.bean.UserFactory"></bean>
属性注入方式
假定存在:
User.java
package cn.itcast.bean;
public class User {
private String name;
private Integer age;
private Car car;
public User() {
System.out.println("User对象空参构造方法!!!!");
}
public User(String name, Car car) {
System.out.println("User(String name, Car car)!!");
this.name = name;
this.car = car;
}
public User(Car car,String name) {
System.out.println("User(Car car,String name)!!");
this.name = name;
this.car = car;
}
public User(Integer name, Car car) {
System.out.println("User(Integer name, Car car)!!");
this.name = name+"";
this.car = car;
}
//get、set、toString方法省略
}
Car.java
package cn.itcast.bean;
public class Car {
private String name;
private String color;
//get、set、toString方法省略
}
applicationContext.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 ">
<!-- 将car对象配置到容器中 -->
<bean name="car" class="cn.itcast.bean.Car" >
<property name="name" value="兰博基尼" ></property>
<property name="color" value="黄色" ></property>
</bean>
</beans>
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>
构造函数注入
<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>
因为存在两个构造参数:User(String name, Car car)h和User(Integer name, Car car),
只根据name属性无法断定应执行哪个,需要type属性指明参数类型,如果不存在此问题可以省略type属性。
因为存在两个构造参数:User(String name, Car car)h和User(Car car,String name),
只根据name属性无法断定应执行哪个,需要index属性指明参数位置,如果不存在此问题可以省略index属性。
p名称空间注入
使用该方法需要在beans元素中导入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>
spel语言注入
Spring Expression Language sping表达式语言。
可以实现从别的bean取值过来。
<bean name="user4" class="cn.itcast.bean.User" >
<property name="name" value="#{user.name}" ></property>
<property name="age" value="#{user3.age}" ></property>
<property name="car" ref="car" ></property>
</bean>
复杂类型注入
<bean name="cb" class="cn.itcast.c_injection.CollectionBean" >
<!-- 如果数组中只准备注入一个值(对象),直接使用value|ref即可
<property name="arr" value="tom" ></property>
-->
<!-- array注入,多个元素注入 -->
<property name="arr">
<array>
<value>tom</value>
<value>jerry</value>
<ref bean="user4" />
</array>
</property>
<!-- 如果List中只准备注入一个值(对象),直接使用value|ref即可
<property name="list" value="jack" ></property>-->
<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>
<!-- prperties 类型注入 -->
<property name="prop" >
<props>
<prop key="driverClass">com.jdbc.mysql.Driver</prop>
<prop key="userName">root</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>
使用@注释代替bean元素
Spring支持使用@注解代替xml配置文件中的bean元素。
导包
Spring4个核心包+2个apache日志包+spring-aop
配置Spring配置文件
引入命名空间
打开Spring配置文件,按如下步骤操作。
Preferences->XML Catelog->File System->找到spring的schema/context/XXXX(最新版).xsd->打开->Key type选择Schema location->把约束文件名(XXXX.xsd)粘贴到Key输入框的最后面->OK->
输入beans元素->切换到设计视图->在beans元素上点击右键->Edit Namespaces->->Add...->Specify New Namespace->Browse->Select XML Catelog entry->找到刚才导入的XXX.xsd->OK->把Location Hint的路径(去掉文件名:/XXX.xsd)粘贴到Namespace Name中->在Prefix中输入“context”->OK。
如果在beans中输入<context:有提示,就说明约束导入成功了。
配置Spring配置文件
在Spring配置文件的beans元素中插入context:component-scan元素,Spring会自动扫描指定包中所有类的注解配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">
<!-- 指定扫描cn.itcast.bean报下的所有类中的注解.
注意:扫描包时.会扫描指定报下的所有子孙包
-->
<context:component-scan base-package="cn.itcast.bean"></context:component-scan>
</beans>
配置需要Spring管理的类
打开需要Spring管理的类,在类中加@注释实现由Spring创建管理。
在类的上一行加入@Component("名字")注解即可,也可以使用以下几种注释代替:
- @Service("名字")
service层 -
@Controller("名字")
web层 -
@Repository("名字")
dao层
几种注释之间功能没有任何区别,只是为了体现出类的分层。
值的注入
- @Value("值")
可以在成员变量前面或set方法前面使用@Value("值")来注入值。
public class Test{
@Value(123)//相当于a = 123
int a;
@Value(123)//相当于调用了setA(123)
public setA(int a){
this.a = a;
System.out.println("调用了set!");
}
}
在成员变量前面使用更直观清晰,但是没有经过set方法,失去了封闭性。
在set方法前面使用按逻辑来说是正确的做法,推荐使用,但是不那么直观清晰。
引用的注入
- @Autowired
自动装配,会自动找到类型一致的对象装配给他。
问题:如果匹配多个类型一致的对象.将无法选择具体注入哪一个对象. -
@Qualifier("名字")
根据名字自动装配。 -
@Resource(name="名字")
手动注入,推荐。
初始化、销毁方法
-
@PostConstruct
在对象被创建后会调用 -
@PreDestroy
在销毁之前调用
设定范围
@Scope(scopeName="singleton")
singleton:单例
prototype:多例
代码实例
User.java
package cn.itcast.bean;
//导包代码省略
// @Service("user") // service层
// @Controller("user") // web层
// @Repository("user")// dao层
//指定对象的作用范围
@Component("user")
@Scope(scopeName="singleton")//设定作用范围
public class User {
private String name;
@Value("18")
private Integer age;
//@Autowired //自动装配
//@Qualifier("car2")//指定名称注入
@Resource(name="car")//手动注入
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String getName() {
return name;
}
@Value("tom")//通过set方法注入值
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@PostConstruct //在对象被创建后调用
public void init(){
System.out.println("我是初始化方法!");
}
@PreDestroy //在销毁之前调用
public void destory(){
System.out.println("我是销毁方法!");
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
}
}
Comments | NOTHING