Spring
简介
分层的Java SE/EE应用 full - stack轻量级开源框架。
核心:IOC(Inverse Of Control 控制反转)和AOP(Aspect Oriented Programming 面向切面编程)
优势
- 方便解耦,简化开发
- AOP编程的支持
- 声明式事务的支持
- 方便程序的测试
- 方便集成各种优秀框架
- 降低JAVAEE API的使用难度
- Java源码经典学习范例
体系结构
1. Data Access/Integration(数据访问/集成)
数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块,具体介绍如下。
- JDBC 模块:提供了一个 JDBC 的抽象层,大幅度减少了在开发过程中对数据库操作的编码。
- ORM 模块:对流行的对象关系映射 API,包括 JPA、JDO、Hibernate 和 iBatis 提供了的集成层。
- OXM 模块:提供了一个支持对象/XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。
- JMS 模块:指 Java 消息服务,包含的功能为生产和消费的信息。
- Transactions 事务模块:支持编程和声明式事务管理实现特殊接口类,并为所有的 POJO。
2. Web 模块
Spring 的 Web 层包括 Web、Servlet、Struts 和 Portlet 组件,具体介绍如下。
- Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IoC 容器初始化以及 Web 应用上下文。
- Servlet模块:包括 Spring 模型—视图—控制器(MVC)实现 Web 应用程序。
- Struts 模块:包含支持类内的 Spring 应用程序,集成了经典的 Struts Web 层。
- Portlet 模块:提供了在 Portlet 环境中使用 MV C实现,类似 Web-Servlet 模块的功能。
3. Core Container(核心容器)
Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 Expression Language 表达式语言模块组成,具体介绍如下。
- Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。
- Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能。
- Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。
- Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。
Spring程序开发步骤
- 导入Spring开发的基本包坐标(Maven)
- 编写Dao接口和实现类
- 创建配置文件
- 在配置文件中配置实现类
- 使用Spring中API获取Bean实例
创建Maven项目
-
在pom.xml导入Spring开发的基本包坐标(导入坐标)
<!--导入spring的context坐标,context依赖core、beans、expression--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
-
编写Dao接口和实现类
public interface UserDao { public void save(); } public class UserDaoImpl implements UserDao { public void save() { System.out.println("Hello"); } }
-
在类路径下(resources)创建
applocationContext.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"> //配置对应userDao的实现类 <bean id="userDao" class="dao.impl.UserDaoImpl"></bean> </beans>
-
测试
public class UserDaoDemo { public static void main(String[] args) { //创建ApplicationContext对象 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); //通过getBean方法获取配置文件中Bean(指定的对象) UserDao userDao = (UserDao) app.getBean("userDao"); userDao.save(); } } //结果:Hello
Spring配置文件
Bean标签基本配置
默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功
bean
- 类型:标签·
- 归属:beans标签
- 作用:定义spring中的资源,受此标签定义的资源将受到spring控制
- 格式:
<beans>
<bean id="beanId" name="beanName1,beanName2" class="ClassName"></bean>
</beans>
- 基本属性:
<bean id="beanId" name="beanName1,beanName2" class="ClassName"></bean>
/*
id:bean的名称,通过id值获取bean(对象),唯一性标识
class:Bean的全限定名称
name:bean的名称,可以通过name值获取bean,用于多人配合时给bean起别名
*/
Bean标签范围配置
scope
-
类型:属性
-
归属:bean标签
-
作用:定义bean的作用范围
-
格式:
<bean id="userDao" class="dao.impl.UserDaoImpl" scope="singleton"></bean>
-
取值:
-
singleton:
实例化个数:1
实例化时机:Spring容器被创建,加载配置文件时创建对象。
**销毁:**应用卸载,销毁容器时
-
prototype:设定创建出的对象保存在spring容器中,
实例化个数:多个
实例化时机:在调用getBean方法时创建对象
**销毁:**创建的对象长时间不用时(不可达判定二次标记),被GC回收了
-
request、session、application、 websocket :设定创建出的对象放置在web容器对应的位置
-
Bean生命周期配置
init-method:
指定类中的初始化方法名称
destroy-method:
指定类中的销毁方法名称
-
归属:bean标签
-
作用:定义bean对象在初始化或销毁时完成的工作
-
格式
<bean id="userDao" class="dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>
-
注意事项:
当scope=“singleton”时,spring容器中有且仅有一个对象,init方法在创建容器时仅执行一次
当scope=“prototype”时,spring容器要创建同一类型的多个对象,init方法在每个对象创建时均执行一次
当scope=“singleton”时,关闭容器会导致bean实例的销毁,调用destroy方法一次
当scope=“prototype”时,对象的销毁由垃圾回收机制gc()控制,destroy方法将不会被执行
Bean实例化三种方式
-
无参构造方法实例化(重要)
<!-- 无参构造创建对象--><bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" </bean>
-
工厂静态方法实例化(了解)
/** * 定义工厂静态方法实例化 */ public class StaticFactory { public static UserDao getUserDao(){ return new UserDaoImpl(); } }
<!-- 工厂静态方法实例化配置--> <bean id="userDao" class="factory.StaticFactory" factory-method="getUserDao"></bean>
-
工厂实例方法实例化(了解)
//工厂实例方法实例化 public UserDao getUserDao1(){ return new UserDaoImpl(); }
<!-- 工厂实例方法实例化配置--> <!-- 先获取StaticFactory对象--> <bean id="factory" class="factory.StaticFactory"></bean> <!-- 再去调用实例方法实例化--> <bean id="userDao" factory-bean="factory" factory-method="getUserDao1"></bean>
Bean依赖的注入
依赖注入概念
- DI(Dependency Injection)依赖注入,应用程序运行依赖的资源由Spring为其提供,资源进入应用程序的方式称为注入。Spring框架核心IOC的具体实现
- 在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层(Service)仍会调用持久层(Dao)的方法。
- 简单的说,就是坐等框架把持久层(Dao)对象传入业务层(Service),而不用我们自己去获取。
依赖注入方式
- 构造方法
- set方法
set方法注入
-
名称:property
-
类型:标签
-
归属:bean标签
-
作用:使用set方法的形式为bean提供资源
-
格式:
<bean> <property /></bean>
<bean id="userDao" class="dao.impl.UserDaoImpl"></bean><bean id="userService" class="service.impl.UserServiceImpl"> <!-- set方法注入 --> <!-- name对应set方法,例如 setUserDao方法去掉set,之后首字母小写-userDao--> <!-- ref 将bean 中 id为userDao引入--> <property name="userDao" ref="userDao" ></property></bean>
name
:对应bean中的属性名,要求该属性必须提供可访问的set方法(严格规范为此名称是set方法对应名称)
value
:设定非引用类型属性对应的值,不能与ref同时使用
ref
:设定引用类型属性对应bean的id ,不能与value同时使用
使用p命名空间简化配置(了解)
使用p命令空间需要先开启spring对p命令空间的的支持,在beans标签中添加对应空间支持
xmlns:p="http://www.springframework.org/schema/p"
例子
<bean id="userService" class="service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
和上面使用property相对比,变得简介了。
构造方式注入
-
名称:constructor-arg
-
类型:标签
-
归属:bean标签
-
作用:使用构造方法的形式为bean提供资源,兼容早期遗留系统的升级工作
-
格式:
<bean> <constructor-arg /></bean>
例子
<!-- 构造方法注入--> <bean id="userService" class="service.impl.UserServiceImpl"><!-- name指的是构造函数中的参数名userDao--><!-- public UserServiceImpl(UserDao userDao) {--><!-- this.userDao = userDao;--><!-- }--><!-- ref指bean 中 id为userDao引入--> <constructor-arg name="userDao" ref="userDao"></constructor-arg> </bean>
name
:对应bean中的构造方法所携带的参数名
ref
:设定**引用类型(对象)**构造方法参数对应bean的id ,不能与value同时使用
<constructor-arg index="arg-index" type="arg-type" ref="beanId" value=""/>
value
:设定**非引用类型(基本数据类型)**构造方法参数对应的值,不能与ref同时使用
type
:设定构造方法参数的类型,用于按类型匹配参数或进行类型校验
index
:设定构造方法参数的位置,用于按位置匹配参数,参数index值从0开始计数
注意:一个bean可以有多个constructor-arg标签
依赖注入数据类型
之前都是对象数据的引入,接下来介绍基本数据类型的引用
对于集合数据类型注入:
-
名称:array,list,set,map,props
-
归属:property标签 或 constructor-arg标签
-
作用:注入集合数据类型属性
-
普通数据注入
public class User {
private String name ;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
对应xml文件中的配置
<bean id="user" class="entity.User">
<!-- name是属性名,也就是setUsername方法去掉set,之后首字母小写-->
<!-- name是属性名,也就是setAge方法去掉set,之后首字母小写-->
<!-- 普通值的注入,用value-->
<property name="name" value="汤姆猫"></property>
<property name="age" value="12"></property>
</bean>
<bean id="user1" class="entity.User">
<property name="name" value="杰瑞"></property>
<property name="age" value="8"></property>
</bean>
- List类型注入
//集合
private List<String> strList;
public void setStrList(List<String> strList) {
this.strList = strList;
}
对应xml文件中的配置
<bean id="baseDataDao" class="dao.impl.BaseDataImpl">
<property name="strList">
<!-- list类型-->
<list>
<!-- value对应非引用数据类型,ref对应引用数据类型-->
<value>赵信</value>
<value>卡莎</value>
<value>薇恩</value>
</list>
</property>
</bean>
- Map类型注入
private Map<String, User> userMap; public void setUserMap(Map<String, User> userMap) { this.userMap = userMap; }
对应xml文件中的配置
<bean id="baseDataDao" class="dao.impl.BaseDataImpl"> <property name="userMap"> <!-- map类型--> <map> <entry key="key1" value-ref="user"></entry> <entry key="key2" value-ref="user1"></entry> </map> </property> </bean>
- Properties注入
private Properties properties; public void setProperties(Properties properties) { this.properties = properties; }
对应xml文件中的配置
<bean id="baseDataDao" class="dao.impl.BaseDataImpl"> <property name="properties"> <props> <prop key="p1">北京</prop> <prop key="p2">南京</prop> </props> </property> </bean>
团队开发
import 一般用于团队开发使用,可以将多个 beans.xml 配置文件,导入合并为一个。
-
类型:标签
-
归属:beans标签
-
作用:在当前配置文件中导入其他配置文件中的项
-
格式:
<beans> <import /></beans>
-
基本属性:
<import resource=“config.xml"/>
resource:加载的配置文件名
-
Spring容器加载多个配置文件
new ClassPathXmlApplicationContext("config1.xml","config2.xml");
-
Spring容器中的bean定义冲突问题
- 同id的bean,后定义的覆盖先定义的
- 导入配置文件可以理解为将导入的配置文件复制粘贴到对应位置
- 导入配置文件的顺序与位置不同可能会导致最终程序运行结果不同
Spring相关API
applicationContext接口
applicationContext :接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象
applicationContext实现类
ClassPathXmlApplicationContext : 它是从类的根路径下加载配置文件,推荐使用这种
FileSystemXmlApplicationContext : 它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置
AnnotationConfigApplicationContext : 当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解
getBean()方法
getBean(“id”) : 当参数的数据类型是字符串时,表示根据 Bean 的 id 从容器中获得Bean实例,返回是Object,需要强转。
getBean(Class) :当参数的数据类型是Class字节码类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,
则此方法会报错。