Spring5
概述
- Spring 是轻量级的开源的 JavaEE 框架
- Spring 可以解决企业应用开发的复杂性
- Spring 有两个核心部分:IOC 和 Aop
(1)IOC:控制反转,把创建对象的过程交给 Spring 进行管理
(2)Aop:面向切面,不修改源代码进行功能增强 - Spring 特点:
(1)方便解耦,简化开发
(2)Aop 编程支持
(3)方便程序测试
(4)方便和其他框架进行整合
(5)方便进行事务操作
(6)降低 API 开发难度
入门代码
编写一个 Spring 程序:
-
下载 Spring 相关的 jar 包。
-
导入 Spring 核心 jar 包。
Spring 需要依赖 logging 日志包。 -
使用 eclipse 编程时,需要安装 Spring 插件。
在 Help => Eclipse Marketplace => 搜索 sts => 安装下图插件
-
编写 User.java 类。
在 com.mcc.spring5 包下package com.mcc.spring5; public class User { public void add() { System.out.println("method add"); } }
-
配置 Spring 配置文件,使用 xml 格式。
注意:Spring 配置文件默认位置在/WEB-INF/
下,默认名称为:applicationContext.xml
新建 Spring Bean Configuration File 文件,名称为:bean1.xml
配置文件内容如下:bean1.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"> <!-- 配置 User 对象 --> <bean id="user" class="com.mcc.spring5.User"></bean> </beans>
其中,id 表示所配置对象的别名,class 表示该对象的全类名。
-
编写测试代码。
在 com.mcc.test 包下package com.mcc.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mcc.spring5.User; public class TestSping5 { @Test public void testUser() { //1. 加载 Spring 配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); //2. 获取配置文件中创建的对象 /* * getBean(String name, Class clazz) * 将配置文件中 id = name */ User user = context.getBean("user", User.class); System.out.println(user); //3. 调用方法 user.add(); } }
IOC 容器
原理
- 什么是 IOC( Inversion of Control )?
(1)控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理。
(2)使用 IOC 的目的:为了降低代码间的耦合度。
(3)入门案例就是 IOC 的实现过程。 - IOC 底层原理:
xml 解析、工厂模式、反射 - 图示:
第一步:spring 配置文件,使用 xml 配置要创建的对象
第二步:假设有 UserService 类和 UserDao 类,UserService 类调用 UserDao 类的方法实现某些功能,因此在UserService 类内要创建 UserDao 类的对象,通过创建工厂类实现。
BeanFactory 接口
- IOC 思想基于 IOC 容器完成,IOC 容器底层是对象工厂。
- Spring 提供两种方式实现 IOC 容器:(两个接口)
(1)BeanFactory 接口:IOC 容器的最基本实现方式,是 Spring 内部使用的接口,不提供开发人员进行使用
特点:加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
(2)ApplicationContext 接口:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
特点:加载配置文件时候就会把在配置文件对象进行创建 - ApplicationContext 接口的常用实现类:
FileSystemXmlApplicationContext 类:加载磁盘上的配置文件
ClassPathXmlApplicationContext 类:加载 src 文件夹下的配置文件
AnnotationConfigApplicationContext 类:加载配置类
IOC 操作—Bean 管理
-
什么是 Bean 管理?
Bean 管理指的是两个操作:
(1)Spring 创建对象
(2)Spirng 注入属性 -
Bean 管理的两种方式:
(1)基于 xml 配置文件方式实现
(2)基于注解方式实现
基于 xml 配置文件实现
创建对象
创建 Bean 对象,可以在 xml 配置文件中通过 bean 标签实现,bean 标签的属性:
- id 属性:对象的唯一标识
- class 属性:对象的全类名
<!-- 配置 User 对象 -->
<bean id="user" class="com.mcc.spring5.User"></bean>
创建对象时,默认执行无参构造器完成对象的创建。
注入属性
DI:依赖注入,就是注入属性。
第一种注入方式:使用 set() 方法进行注入,必须要有无参构造器
步骤:
(1)创建类,定义属性和对应的 set() 方法
package com.mcc.spring5;
public class User {
private int id;
private String name;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
public void show() {
System.out.println("method show");
}
}
(2)在 spring 配置文件中注入属性
<!-- 配置 User 对象 -->
<bean id="user" class="com.mcc.spring5.User">
<!--
使用 property 标签完成属性注入
name:类里面属性的名称
value:向属性注入的值
-->
<property name="id" value="001"></property>
<property name="name" value="佐助"></property>
</bean>
测试:
@Test
public void testUser() {
//1. 加载 Spring 配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2. 获取配置文件中创建的对象
/*
* getBean(String name, Class clazz)
* 将配置文件中 id = name
*/
User user = context.getBean("user", User.class);
System.out.println(user);//User [id=1, name=佐助]
//3. 调用方法
user.show();//method show
}
第二种注入方式:使用有参构造器进行注入
步骤:
(1)创建类,定义属性和有参构造器
package com.mcc.spring5;
public class Book {
private String bname;
private String bauthor;
public Book(String bname, String bauthor) {
super();
this.bname = bname;
this.bauthor = bauthor;
}
@Override
public String toString() {
return "Book [bname=" + bname + ", bauthor=" + bauthor + "]";
}
public void show() {
System.out.println("method show");
}
}
(2)在 spring 配置文件中注入属性
<!-- 配置 Book 对象 -->
<bean id="book" class="com.mcc.spring5.Book">
<!--
使用 有参构造器 进行属性注入时:
使用 constructor-arg 标签完成属性注入
name:类里面属性的名称
value:向属性注入的值
-->
<constructor-arg name="bname" value="西游记"></constructor-arg>
<constructor-arg name="bauthor" value="施耐庵"></constructor-arg>
</bean>
测试:
@Test
public void testBook() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Book book = context.getBean("book", Book.class);
System.out.println(book);
book.show();
}
p 名称空间注入(了解)
简化了 set() 方法注入时的操作,不需要使用 property 标签。
步骤:
(1)在 beans 标签中加入:xmlns:p="http://www.springframework.org/schema/p"
(2)在 bean 标签中使用p:属性="值"
完成属性注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置 User 对象 -->
<bean id="user1" class="com.mcc.spring5.User" p:id="002" p:name="鸣人"></bean>
</beans>
null 值以及特殊字符的注入
-
null 值的注入:
使用<null/>
标签实现property 标签下:
<bean id="user2" class="com.mcc.spring5.User"> <property name="id" value="003"></property> <property name="name"> <null/> </property> </bean>
constructor-arg 标签下:
<bean id="book1" class="com.mcc.spring5.Book"> <constructor-arg name="bname" value="Java从入门到精通"></constructor-arg> <constructor-arg name="bauthor"> <null/> </constructor-arg> </bean>
-
特殊字符的注入:
使用转义字符或<![CDATA[]]>
实现<bean id="book2" class="com.mcc.spring5.Book"> <constructor-arg name="bname" value="<数据结构与算法>"></constructor-arg> <constructor-arg name="bauthor"> <value><![CDATA[<???>]]></value> </constructor-arg> </bean>
外部 Bean 的注入
接口:UserDao,UserService
类:UserDaoImpl,UserServiceImpl
UserServiceImpl 类中要使用 UserDaoImpl 对象完成功能的实现,
此时,在 UserServiceImpl 类中引用 UserDaoImpl 对象,就是外部Bean 的注入。
UserDao.java
package com.mcc.spring5.dao;
public interface UserDao {
public void update();
}
UserService.java
package com.mcc.spring5.service;
public interface UserService {
public void add();
}
UserDaoImpl.java
package com.mcc.spring5.dao;
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println("dao update");
}
}
UserServiceImpl.java
package com.mcc.spring5.service;
import com.mcc.spring5.dao.UserDao;
public class UserServiceImpl implements UserService{
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void add() {
System.out.println("service add");
userDao.update();
}
}
Spring 配置文件 bean2.xml
使用 property 标签 或 constructor-arg 标签的 ref 属性完成
- name 属性:对象的属性名
- ref 属性:需要注入的 Bean 对象的 id 值
<?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">
<!-- 配置 UserDaoImpl 对象 -->
<bean id="userDaoImpl" class="com.mcc.spring5.dao.UserDaoImpl"></bean>
<!-- 配置 UserServiceImpl 对象 -->
<bean id="userServiceImpl" class="com.mcc.spring5.service.UserServiceImpl">
<!--
注入外部Bean
name 属性:对象的属性名
ref 属性:需要注入的 Bean 对象的 id 值
-->
<!-- 注入 UserDaoImpl 对象 -->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
</beans>
测试
public class TestRefBean {
@Test
public void testUserService() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
UserService userService = context.getBean("userServiceImpl", UserService.class);
userService.add();
//service add
//dao update
}
}
内部 Bean 的注入
类:Department、Employee
一个部门有多个员工,一个员工只属于一个部门
Department.java
package com.mcc.spring5.bean;
public class Department {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
@Override
public String toString() {
return "Department [dname=" + dname + "]";
}
}
Employee.java
package com.mcc.spring5.bean;
public class Employee {
private String ename;
private String gender;
private Department dept;
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setDept(Department dept) {
this.dept = dept;
}
public Department getDept() {
return dept;
}
public void show() {
System.out.println(ename + "::" + gender + "::" + dept.toString());
}
}
Spring 配置文件 bean3.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">
<!-- 创建 Employee 对象 -->
<bean id="employee" class="com.mcc.spring5.bean.Employee">
<property name="ename" value="张三"></property>
<property name="gender" value="男"></property>
<property name="dept">
<!-- 内部Bean实现 -->
<bean id="department" class="com.mcc.spring5.bean.Department">
<property name="dname" value="技术部"></property>
</bean>
</property>
</bean>
</beans>
测试
public class TestInnerBean {
@Test
public void testEmployee {
ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
Employee employee = context.getBean("employee", Employee.class);
employee.show();//张三::男::Department [dname=技术部]
}
}
级联赋值
第一种方式:
<!-- 级联赋值 方式1 -->
<!-- 创建 Employee 对象 -->
<bean id="employee01" class="com.mcc.spring5.bean.Employee">
<property name="ename" value="张三"></property>
<property name="gender" value="男"></property>
<property name="dept" ref="department01"></property>
</bean>
<!-- 创建 Department 对象 -->
<bean id="department01" class="com.mcc.spring5.bean.Department">
<property name="dname" value="财务部"></property>
</bean>
第二种方式:
这种方式要获取到 dept.dname 的前提是能获取到 Department dept 对象,因此,这种方式依赖于 Employee 类内的 getDept() 方法。
<!-- 级联赋值 方式2 -->
<!-- 创建 Employee 对象 -->
<bean id="employee02" class="com.mcc.spring5.bean.Employee">
<property name="ename" value="李四"></property>
<property name="gender" value="男"></property>
<property name="dept" ref="department02"></property>
<property name="dept.dname" value="人事部"></property>
</bean>
<!-- 创建 Department 对象 -->
<bean id="department02" class="com.mcc.spring5.bean.Department"></bean>
测试
@Test
public void testEmployee01() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Employee employee = context.getBean("employee01", Employee.class);
employee.show();//张三::男::Department [dname=财务部]
}
@Test
public void testEmployee02() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Employee employee = context.getBean("employee02", Employee.class);
employee.show();//李四::男::Department [dname=人事部]
}
集合属性的注入
1. 集合中存放的是普通类型的数据
Student.java
package com.mcc.spring5.collection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Student {
private String[] courses;
private Set<String> set;
private List<String> list;
private Map<String,String> map;
public String[] getCourses() {
return courses;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
@Override
public String toString() {
return "Student [courses=" + Arrays.toString(courses) + ", set=" + set + ", list=" + list + ", map=" + map
+ "]";
}
}
Spring 配置文件 collection.xml
集合 | 使用的标签 |
---|---|
数组 | <array> |
Set | <set> |
List | <list> |
Map | <map> <entry> |
<?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">
<bean id="student" class="com.mcc.spring5.collection.Student">
<property name="courses">
<array>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</array>
</property>
<!-- 为 Set 集合赋值 -->
<property name="set">
<set>
<value>长春</value>
<value>沈阳</value>
<value>北京</value>
</set>
</property>
<!-- 为 List 集合赋值 -->
<property name="list">
<list>
<value>火车</value>
<value>飞机</value>
<value>轮船</value>
</list>
</property>
<!-- 为 Map 集合赋值 -->
<property name="map">
<map>
<entry key="1" value="本科"></entry>
<entry key="2" value="硕士"></entry>
<entry key="3" value="博士"></entry>
</map>
</property>
</bean>
</beans>
测试
public class TestCollection {
@Test
public void testCollection() {
ApplicationContext context = new ClassPathXmlApplicationContext("collection.xml");
Student stu = context.getBean("student", Student.class);
System.out.println(stu.toString());
//Student [courses=[语文, 数学, 英语], set=[长春, 沈阳, 北京], list=[火车, 飞机, 轮船], map={1=本科, 2=硕士, 3=博士}]
}
}
2. 集合中存放的是对象类型的数据
Student.java
package com.mcc.spring5.collection;
import java.util.List;
public class Student {
private String name;
private List<Course> courseList;//学生所学的多门课程
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getCourseList() {
return courseList;
}
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
@Override
public String toString() {
return "Student [name=" + name + ", courseList=" + courseList + "]";
}
}
Course.java
package com.mcc.spring5.collection;
public class Course {
private String cname;
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Course [cname=" + cname + "]";
}
}
Spring 配置文件 collection.xml
通过在集合标签中使用 <ref/>标签,完成向集合中传入对象类型的数据。
- ref 标签中的 bean 属性:要传入到集合中的对象的 id 值。
<?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">
<bean id="student" class="com.mcc.spring5.collection.Student">
<!-- 为 name 属性赋值 -->
<property name="name" value="张三"></property>
<!-- 为 courseList 赋值 -->
<property name="courseList">
<list>
<ref bean="course01"/>
<ref bean="course02"/>
</list>
</property>
</bean>
<!-- 创建 Course 对象 -->
<bean id="course01" class="com.mcc.spring5.collection.Course">
<property name="cname" value="Spring5框架"></property>
</bean>
<bean id="course02" class="com.mcc.spring5.collection.Course">
<property name="cname" value="MyBatis"></property>
</bean>
</beans>
测试
public class TestCollection {
@Test
public void testCollection() {
ApplicationContext context = new ClassPathXmlApplicationContext("collection.xml");
Student stu = context.getBean("student", Student.class);
System.out.println(stu.toString());
//Student [name=张三, courseList=[Course [cname=Spring5框架], Course [cname=MyBatis]]]
}
}
3. 提取集合部分,以供多个对象注入
Book.java
package com.mcc.spring5.collection;
import java.util.List;
public class Book {
private List<String> bookList;
public List<String> getBookList() {
return bookList;
}
public void setBookList(List<String> bookList) {
this.bookList = bookList;
}
@Override
public String toString() {
return "Book [bookList=" + bookList + "]";
}
}
Spring 配置文件 bookCollection.xml
要提取集合部分,供其他对象进行属性注入,首先要引入 util名称空间,xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- List 集合属性,抽取出来,以供其他对象进行注入 -->
<util:list id="bookList">
<value>仲夏夜之梦</value>
<value>威尼斯商人</value>
<value>皆大欢喜</value>
<value>第十二夜</value>
</util:list>
<!-- 创建 Book 对象,并注入 List 属性 -->
<bean id="book" class="com.mcc.spring5.collection.Book">
<property name="bookList" ref="bookList"></property>
</bean>
</beans>
测试
@Test
public void testBookCollection() {
ApplicationContext context = new ClassPathXmlApplicationContext("bookCollection.xml");
Book book = context.getBean("book", Book.class);
System.out.println(book);//Book [bookList=[仲夏夜之梦, 威尼斯商人, 皆大欢喜, 第十二夜]]
}