1、Spring框架概述
1、Spring是轻量级 的开源 的JavaEE框架
2、Spring可以解决企业应用开发的复杂性
3、Spring有两个核心部分:IOC
和 Aop
(1)IOC:控制反转,把创建对象过程交给Spring管理
(2)Aop:面向切面,不修改源代码进行功能增强
4、Spring特点
(1)方便解耦,简化开发
(2)Aop编程支持
(3)方便程序测试
(4)方便和其他框架进行整合
(5)方便进行事务操作
(6)降低API开发难度
5、选取Spring版本5.x学习
2、Spring框架下载
Spring官网:https://spring.io/projects/spring-framework#learn
下载网址:https://repo.spring.io/release/org/springframework/spring/
5.2.6RELEASE版本
spring-5.2.6.RELEASE-dist.zip
3、案例
3.1 创建一个普通的java项目
导入4个jar包
spring-beans-5.2.6.RELEASE
spring-context-5.2.6.RELEASE
spring-core-5.2.6.RELEASE
spring-expression-5.2.6.RELEASE
commons-logging-1.1.1 //还要导入这个日志包,否则会报错
3.2 在项目中添加依赖
3.3 在项目中创建一个普通的类
public class User {
public void add(){
System.out.println("add.....");
}
}
3.4 创建 Spring 配置文件,在配置文件中配置创建的对象
(1)Spring配置文件使用xml
bean有两个属性,id是自己起的名字,class是类所在路径
<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="user" class="com.qy.spring5.User">bean>
beans>
3.5 进行测试代码编写
@Test
public void testAdd(){
// 1 加载 Spring 配置文件
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("com/qy/spring5/bean1.xml");
// 2 获取配置创建的对象
User user = context.getBean("user", User.class);
// 3 调用获取配置创建的对象的方法
user.add();
// 4 输出创建的对象
System.out.println(user);
}
4、IOC容器
(1)IOC底层原理
(2)IOC接口(BeanFactory)
(3)IOC操作Bean管理(基于xml)
(4)IOC操作Bean管理(基于注解)
1、什么是IOC
(1)控制反转,把对象创建和对象之间的调用过程,交给Spring管理
(2)使用IOC目的:为了耦合度降低
(3)做入门案例就是IOC实现
2、IOC底层原理
(1)xml解析、工厂模式、反射
3、讲解一下IOC底层原理
假设现在有两个类
UserDao和UserService
(方便起见,我们写在一个框里)
4.1 IOC底层原理
原始情况:UserService调用UserDao是如何调用的呢?
我们要在UserService中创建一个UserDao,然后再进行调用,但是这样的话导致了UserService和UserDao的耦合度很高,如果UserDao的方法或者路径变化,那么UserService也会变化。
//UserService类
public class UserService{
execute(){
UserDao dao = new UserDao();
dao.add();
}
}
------
//UserDao类
public class UserDao{
add(){
......
}
}
工厂模式
我们有一个工厂类,来统一的创建对象,使用的话只需要调用工厂类来获得这个对象。
Factory.class UserService.class UserDao.class
UserService使用UserDao的时候,通过工厂类来获得UserDao,降低了UserService和UserDao的耦合度,
但是Factory和UserDao还是有耦合度的(耦合度并不会消失,只能尽可能的小)
这样UserDao改变了的话,UserService并不会改变。
class UserService{
execute(){
UserDao dao = Factory.getDao();
dao.add();
}
}
---
class UserDao{
add(){
......
}
}
---
//工厂类
class Factory{
public static UserDao getDao(){
return new UserDao();
}
}
4.1.1 IOC 解耦过程
IOC没有使耦合度消失,只是降低了耦合度,比如说,如果UserDao的路径改变了,那么只需要在xml配置文件中修改class属性即可,不需要修改工厂类。
-
第一步 xml配置文件 , 配置创建的对象
<bean id="dao" class="com.at.qy.UserDao">bean>
-
第二部 有Service类和Dao类, 创建工厂类
class UserFactory{ public static UserDao getDao(){ String classValue = class属性值; //1 xml解析 Class clazz = Class.forName(classValue); //2 通过反射创建对象 return (UserDao)clazz.newInstance(); } }
4.2 IOC接口
1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
2、Spring提供IOC容器两种实现方式:(两个接口)
(1)BeanFactory:IOC容器的基本实现,是Spring内部的使用接口,不提供开发人员进行使用。
*加载配置文件时,不会创建对象,只有在获取(使用)对象才去创建对象
(2)ApplicationContext:BeanFactory接口的子接口,提供更多强大的功能,一般由开发人员使用
*加载配置文件时候就会把配置文件中所有对象进行创建(下列代码第一步,就是加载配置文件)
@Test
public void testAdd(){
// 1 加载 Spring 配置文件
// ********ApplicationContext可以替换为BeanFactory********
ApplicationContext context =
new ClassPathXmlApplicationContext("com/qy/spring5/bean1.xml");
// 2 获取配置创建的对象
User user = context.getBean("user", User.class);
// 3 调用获取配置创建的对象的方法
user.add();
// 4 输出创建的对象
System.out.println(user);
}
4.3 IOC操作Bean管理
4.3.1 什么是Bean管理?
Bean管理指的是两个操作:
(1)Spring创建对象
(2)Spring注入属性
4.3.2 Bean管理操作有两种方式
(1)基于xml配置文件方式实现
(2)基于注解方式实现
5、IOC操作Bean管理(基于xml方式)
基于xml方式创建对象
(1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
<bean id="user" class="com.qy.spring5.User">bean>
(2)在bean标签有很多属性,介绍常用的属性:
- id属性:唯一标识
- class属性:类全路径(包类路径)
(3)创建对象的时候,默认也是执行无参数的构造方法完成对象创建
基于xml方式注入属性
(1)DI:依赖注入,就是注入属性
第一种注入方式:使用set方法注入
Book类:
public class Book {
private String bname;
private String bauthor;
public void setBname(String bname) {
this.bname = bname;
}
public void setBauthor(String bauthor) {
this.bauthor = bauthor;
}
public String getBname() {
return bname;
}
public String getBauthor() {
return bauthor;
}
}
xml配置文件:
<bean id="book" class="com.qy.spring5.Book">
<property name="bname" value="易经">property>
<property name="bauthor" value="达摩老祖">property>
bean>
测试类:
@Test
public void testBook(){
// 1 加载Spring配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("com/qy/spring5/bean1.xml");
// 2 获取配置创建的对象
Book book = context.getBean("book",Book.class);
// 3 输出配置创建的对象的属性
System.out.println("书名:"+book.getBname()+"作者:"+book.getBauthor());
}
/***************/
输出:书名:易经作者:达摩老祖
第二种注入方式:使用有参构造注入
Order类:
public class Order {
private String oname;
private String address;
public Order(String oname,String address){
this.oname = oname;
this.address = address;
}
public void orderTest(){
System.out.println("订单名称:"+oname+" 订单地址:"+address);
}
}
xml配置文件:
使用有参构造注入要在xml配置文件中加入
标签
<bean id="order" class="com.qy.spring5.Order">
<constructor-arg name="oname" value="电脑">constructor-arg>
<constructor-arg name="address" value="China">constructor-arg>
bean>
测试类:
@Test
public void testOrder(){
// 1 加载Spring配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("com/qy/spring5/bean1.xml");
// 2 获取配置创建的对象
Order order = context.getBean("order",Order.class);
// 3 输出配置创建的对象
System.out.println(order);
order.orderTest();
}
/************************/
输出为:
com.qy.spring5.Order@569cfc36
订单名称:电脑 订单地址:China
基于xml方式注入其他类型属性
1、字面量
(1)null值
给name属性设置为null
<property name="bname">
<null/>
property>
(2)属性值包含特殊符号
例如,我们想要注入属性值为 <<南京>>
<property name="bname" value="<<南京>>">property>
像这样写,因为带有特殊符号,会报错
<property name="bname">
<value>>]]>value>
property>
应该这样写就可以了。
注入属性-外部bean
两个类UserService和UserDao,UserService调用UserDao
UserService类:
public class UserService {
private UserDao userDao;
private void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public void add(){
System.out.println("service......");
}
}
UserDao类:
public class UserDao {
public void update(){
System.out.println("dao update......");
}
}
xml配置文件:
<bean id="userDao" class="com.qy.spring5.dao.UserDao">bean>
<bean id="userService" class="com.qy.spring5.service.UserService">
<property name="userDao" ref="userDao">property>
bean>
注入属性-内部bean和级联赋值
(1)一对多关系:部门和员工
一个部门有多个员工,一个员工属于一个部门
部门是一,员工是多
(2)在实体类之间表示一对多关系
部门类、员工类、xml配置文件
//部门类
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
public String getDeptName(){
return this.dname;
}
}
//员工类
public class Emp {
private String ename;
private String gender;
private Dept dept;
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public void test(){
System.out.println("员工名称:"+ename+" 性别:"+gender+" 部门名称:"+dept.getDeptName());
}
}
//xml配置文件
<bean id="emp" class="com.qy.spring5.DeptTest.Emp">
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<property name="dept">
<bean id="dep" class="com.qy.spring5.DeptTest.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>
//测试类
@Test
public void testOrder(){
// 1 加载Spring配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("com/qy/spring5/bean2.xml");
// 2 获取配置创建的对象
Emp emp = context.getBean("emp", Emp.class);
// 3 输出配置创建的对象
System.out.println(emp);
emp.test();
}
//输出结果
com.qy.spring5.DeptTest.Emp@66d1af89
员工名称:lucy 性别:女 部门名称:安保部
注入属性-级联赋值
<bean id="emp" class="com.qy.spring5.DeptTest.Emp">
<property name="ename" value="lucy">property>
<property name="gender" value="女">property>
<property name="dept" ref="dept">property>
<property name="dept.name" value="技术部">property>
bean>
<bean id="dept" class="com.qy.spring5.DeptTest.Dept">
<property name="dname" value="财务部">property>
bean>
注入集合类型属性
(1)注入数组类型属性
(2)注入 List 集合类型属性
(3)注入 Map 集合
综合案例
Stu类和xml配置文件
//Stu类
public class Stu {
//1 数组类型属性
private String[] courses;
//2 集合类型属性
private List<String> list;
//3 map类型属性
private Map<String,String> maps;
//4 set类型属性
private Set<String> sets;
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
@Override
public String toString() {
return "Stu{" +
"courses=" + Arrays.toString(courses) +
", list=" + list +
", maps=" + maps +
", sets=" + sets +
'}';
}
}
//xml配置文件
<bean id="stu" class="com.qy.spring5.ListTest.Stu">
<!--数组属性注入-->
<property name="courses">
<array>
<value>java课程</value>
<value>数据库课程</value>
</array>
</property>
<!--list属性注入-->
<property name="list">
<list>
<value>大王</value>
<value>小王</value>
</list>
</property>
<!--map属性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="java"