1Spring 是什么?
Spring 是一个开源框架,Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson在其著作 Expert One-On-One J2EE Development and Design 中阐述的部分理念和原型衍生而来。
它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE应用程序开发提供集成的框架。Spring 使用基本的 JavaBean 来完成以前只可能由 EJB 完成的事情。然而,Spring 的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 的核心是控制反转(IOC)和面向切面(AOP)。简单来说,Spring 是一个分层的 轻量级开源框架。
设计模式六大原则(1):单一职责原则http://www.uml.org.cn/sjms/201211023.asp#1
设计模式六大原则(2):里氏替换原则http://www.uml.org.cn/sjms/201211023.asp#2
设计模式六大原则(3):依赖倒置原则http://www.uml.org.cn/sjms/201211023.asp#3
设计模式六大原则(4):接口隔离原则http://www.uml.org.cn/sjms/201211023.asp#4
设计模式六大原则(5):迪米特法则http://www.uml.org.cn/sjms/201211023.asp#5
设计模式六大原则(6):开闭原则http://www.uml.org.cn/sjms/201211023.asp#6
2 为什么使用Spring
- 方便解耦,简化开发
- Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护,交给 Spring 管理
- AOP 编程的支持,Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
- 声明式事务的支持只需要通过配置就可以完成对事务的管理,
- 而无需手动编程方便程序的测试,Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序
- 方便集成各种优秀框架,Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持
- 降低 JavaEE API 的使用难度,Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装,使这些 API 应用难度大大降低
Spring环境搭建
引入spring的依赖
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>4.2.5.RELEASE</spring.version>
</properties>
<!--Spring核心基础依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<!--日志相关-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--测试相关-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
添加配置文件:
配置文件的名字可以任意设置,建议设置为applicationContext.xml,所以这里我们创建一个名为applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
添加相应的模块:
在项目中添加dao、model、service层代码
将bean的实例化交给Spring
<bean name="userDao" class="com.tledu.spring.dao.impl.UserDaoImpl" />
<!--name 属性名字/ref 引用的bean的名字-->
<bean id="userService" class="com.tledu.spring.service.UserService">
<property name="userDao" ref="userDao" />
</bean>
测试类
public class UserServiceTest {
@Test
public void add() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
// userService是bean的id或name
UserService userService = (UserService) applicationContext
.getBean("userService");
userService.add(null);
}
}
通过构造方法注入
bean name="userDao" class="com.tledu.spring.dao.impl.UserDaoImpl" />
<bean id="userService" class="com.tledu.spring.service.UserService">
<constructor-arg ref="userDao"/>
</bean>
普通属性注入
<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
<!-- 如果不是指向对象,直接用value设置值就行 -->
<property name="daoId" value="82"></property>
<property name="daoStatus" value="good"></property>
</bean>
scope
spring中scope是一个非常关键的概念,简单说就是对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式。
目前,scope的取值有5种取值:
在Spring 2.0之前,有singleton和prototype两种;
在Spring 2.0之后,为支持web应用的ApplicationContext,增强另外三种:request,session和global session类型,它们只实用于web程序,通常是和XmlWebApplicationContext共同使用
singleton
此取值时表明容器中创建时只存在一个实例,所有引用此bean都是单一实例。
也就是说创建对象是单例模式,并且如果不进行设置,默认就行单例
prototype
spring容器在进行输出prototype的bean对象 时,会每次都重新生成一个新的对象给请求方,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求 方之后,容器就不在拥有当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁。也就是说,容器每次返回请求方该对象的一 个新的实例之后,就由这个对象“自生自灭”,最典型的体现就是spring与struts2进行整合时,要把action的scope改为 prototype。
简单来说,就是每次获取都创建一个新对象,并且这个对象的生命周期不归Spring管理
配置scope方式
<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl">
<!-- 如果不是指向对象,直接用value设置值就行 -->
<property name="daoId" value="82"></property>
<property name="daoStatus" value="good"></property>
</bean >
<!-- scope singleton : 单例 只创建一个,默认就是
prototype : 每一次getBean 都会创建一个新的实例化对象
request,session : 需要特殊环境支持 -->
<bean id="userService" class="com.tledu.zrz.service.UserService"
scope="singleton">
<!-- 构造方法注入 -->
<constructor-arg>
<ref bean="userDao" />
</constructor-arg>
</bean>
自动装配
上面我们进行对象注入的时候有两种方式
1 set方法注入
<property name="userDao" ref="userDao" />
2 构造方法注入
<constructor-arg>
<ref bean="userDao"/>
</constructor-arg>
现在我们来学习自动注入,就是不需要指定以上两种方式
Autowire : 自动装配,两种取值
1 byName
2 byType
之前servlet的生命周期
构造方法 -- init -- service -- destroy
那么spring创建对象的生命周期呢?
Spring中是没有init、service和destroy的,但是我们可以指定某个方法在创建完对象之后执行,某个方法在最后销毁的时候执行.
生命周期
相关类
UserService中提供对应的方法
public void init(){
System.out.println("init--------");
}
public void destroy(){
System.out.println("destroy----------");
}
public UserService() {
System.out.println("service构造方法");
}
配置文件
<bean name="userDao" class="com.tledu.zrz.dao.impl.UserDaoImpl" >
</bean>
<!--
init-method : 用于设置初始化的方法
destory-method : 用于设置销毁资源的方法
-->
<bean id="userService" class="com.tledu.zrz.service.UserService"
autowire="byName" init-method="init" destroy-method="destroy" >
</bean>
Destroy之所以会执行,是因为我们默认创建对象的时候是单例模式
这个时候对象的生命周期会和Spring容器的生命周期绑定到一起,所以当我们销毁Spring容器的时候,会把所有的对象销毁,并自动调用destroy方法
但是如果我们把scope设置为prototype的时候,对象的生命周期就不会再和Spring容器绑定,销毁Spring容器的时候也就不会再执行该对象的destroy方法
迟加载
Spring容器默认是在执行
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
进行解析的时候创建对象并调用init,
如果我们不想让某个类在解析的时候就创建对象,而是用到的时候在创建对象的话,就需要设置迟加载