1_Spring概念介绍_了解
-
概念

-
Spring 是分层的全栈式的轻量级开发框架, 以IOC和AOP为核心, 官网是 https://spring.io
-
-
Spring版本情况

-
Spring优势
-
1 方便解耦, 简化开发
-
Spring 通过容器, 将对象的创建从代码中剥离出来, 交给 Spring 控制, 避免直接编码造成模块之间的耦合度高, 用户也不必自己编码处理对象的单例和多例控制, 主要关注接口功能即可, 不用关注具体使用哪个实现类和实现细节问题
-
-
2 AOP切面编程
-
AOP 切面编程是程序设计的一种概念, Spring 对该概念实现的比较好, 通过切面编程我们可以在不修改原有代码的情况下实现功能的增加, 通常用于 事务控制, 日志记录, 性能检测, 权限控制等等
-
-
3 声明式事务
-
事务的控制可以托管给 Spring, 我们通过注解或者配置文件声明事务的处理方式即可, 不用我们自己去编码处理
-
-
4 整合JUNIT, 方便测试
-
spring 整合 JUNIT 单元测试, 对于项目的功能都可以进行轻松快速的测试, 便于我们调试程序
-
-
5 方便整合各种优秀的框架
-
SSM > Spring + SpringMVC + MyBatis
-
SSH > Spring + Hibernate + Strust
-
各种其他框架
-
-
6 丰富的功能封装
-
spring 对 JAVAEE(JDBC, JAVAMail,) 都进行了一系列的封装, 简化我们对于API的使用, 提高程序的开发效率
-
-
7 规范的源码学习样本
-
spring 的源码设计巧妙, 结构清晰, 大量使用了设计模式, 是 java 代码规范编写的典范, 也是高级程序员面试中经常会问到的源码
-
-
-
Spring的体系结构

-
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 模块:是运行时查询和操作对象图的强大的表达式语言
-
-
-
4. 其他模块
-
Spring 的其他模块还有 AOP、Aspects、Instrumentation 以及 Test 模块,具体介绍如下
-
AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性
-
Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架
-
Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用
-
Test 模块:支持 Spring 组件,使用 JUnit 或 TestNG 框架的测试
-
-
-
2_Spring_IOC概念引入_重要
-
控制反转
-
概念
-
简单的说就是, 创建对象的权利, 或者是控制的位置, 由 JAVA 代码转移到 spring 容器,由 spring 的容器控制对象的创建, 就是控制反转, spring创建对象时, 会读取配置文件中的信息, 然后使用反射给我们创建好对象之后在容器中存储起来, 当我们需要某个对象时, 通过id获取对象即可, 不需要我们自己去 new
-
一句话: 创建对象交给容器
-
-
-
-
Spring 解耦合的原理
-
图解

-
创建 maven 项目,设置 maven
-
先创建一个空项目

-
名字可以是 spring_all

-
在项目下创建模块 名字可以是 spring_test_01


-
pom.xml 中导入 spring 依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.5</version>
</dependency><dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.5</version>
</dependency><dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.5</version>
</dependency><dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.5</version>
</dependency>
</dependencies>
-
-
四个依赖介绍
-
spring-context 上下文, 容器
-
spring-beans 创建对象
-
spring-core 核心jar
-
spring-expression 表达式jar
-
-
但是事实上, 我们导入 spring-context 的时候, 会自动导入其他依赖的 jar, 自动进行了依赖传递, 所以, 导入一个 spring-context 依赖也可以

-
依赖传递关系图如下

-
为了方便测试, 我们导入 Junit 测试依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency> -
在项目中定义一个接口和实现类
-
EmpDao接口和实现类

-
接口中定义一个方法并在实现类中实现
-
-
接口
public interface EmpDao {
int addEmp();
}-
实现类
public class EmpDaoImp1 implements EmpDao {
@Override
public int addEmp() {
System.out.println("addEmp invoked");
return 0;
}
}-
在 spring 配置容器中的对象
-
创建 spring 配置文件

-
文件名没有明确要求, 暂时可以叫 spring

-
在 spring.xml 中配置一个需要由容器初始化的对象

-
测试通过容器获取对象

-
-
-
3_Spring_IOC原理分析_重要
-
IOC底层原理

-
1 XML解析技术读取配置文件
<bean id="empDao" class="com.xxx.dao.impl.EmpDaoImpl"></bean>
-
将上面的信息读取进入程序 对象的ID, 一个是对象的类的全路径名
-
-
2 反射技术实例化对象, 放到容器中
-
获得类的字节码
-
Class clazz = Class.forName("com.xxx.dao.impl.EmpDaoImpl")
-
-
通过字节码实例化对象
-
Object obj = clazz.newInstance();
-
-
将对象放到一个map集合中
-
map.put("empDao", obj);
-
-
-
3 工厂模式返回 Bean 对象 getBean 方法
public Object getBean(String name){
Object obj = map.get(name);
return obj;
}
-
-
IOC接口
-
BeanFactory
-
接口: IOC 容器基本功能接口, 是 spring 内部使用的接口, 我们在处理业务时一般不直接使用该接口
-
-
ApplicationContext
-
接口: BeanFactory 的子接口, 提供更多更强大的功能, 研发人员一般使用的接口

-
-
4_Spring_XML方式实现DI
-
背景
-
spring中的Bean的管理:
-
Bean(汉译咖啡豆), 又称JAVABean
-
其实就是 JAVA 程序程序中的一个个对象, 所以 Bean 的管理其实就是 spring 对于 JAVA 程序中的对象的管理
-
-
-
管理的内容是什么
-
1 对象的创建 IOC
-
IOC 叫做控制反转, 就是 Spring 给我们创建对象, 然后我们直接用, 不用自己NEW, 前面已经解释过
-
IOC 处理的是对象如何创建的问题
-
-
2 属性的赋值 DI
-
DI Dependency Injection, 即 “依赖注入” 就是创建属性时给对象属性赋值
-
对象功能的实现往往要依赖属性的值, 那么给对象属性赋值就可以说成是依赖注入
-
由于对象属性不仅仅是基本数据类型, 还可能是其他类, 或者引用类型
-
那么依赖注入将会把更多的对象之间的关系整理到一起, 可以形成一个庞大的依赖关系
-
DI 处理的是对象的属性赋值和互相依赖的关系
-
-
-
spring 给我们提供了两种关于 bean 的方式
-
1 基于XML方式的 Bean 管理
-
2 基于注解方式的 Bean 管理
-
创建新的模块并导入以下依赖

-
依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency> -
创建 spring 配置文件,一般 spring 的配置文件很多人约定俗称为 application****.xml

-
准备一个要实例化的类
public class User {
private Integer userid;
private String username;
private String password;@Override
public String toString() {
return "User{" +
"userid=" + userid +
", username='" + username + '\\'' +
", password='" + password + '\\'' +
'}';
}public User() {
System.out.println("noArgConstructor");
}public User(Integer userid, String username, String password) {
System.out.println("allArgConstructor");
this.userid = userid;
this.username = username;
this.password = password;
}public void setUserid(Integer userid) {
System.out.println("setUserid");
this.userid = userid;
}public void setUsername(String username) {
System.out.println("setUsername");
this.username = username;
}public void setPassword(String password) {
System.out.println("setpassword");
this.password = password;
}
}
-
-
IOC 创建对象
-
通过无参构造方法构造对象
<bean id="user1" class="com.xxx.bean.User"></bean>
-
<bean> 标签的常见属性
<bean id="user1" class="com.xxx.bean.User" name="user1" scope="prototype" lazy-init="true"></bean>
-
解释
-
id 对象的id
-
class 类的全路径名
-
name 和id类似,一般不用
-
scope 控制对象单例多例和使用范围
-
singleton 作用域(scope 默认值), Spring IOC 容器中只会存在一个共享的 bean 实例
-
prototype作用域 部署的bean,每一次获取都会产生一个新的bean实例,相当与一个new的操作
-
request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
-
session作用域 表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
-
global session作用域 类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义
-
lazy-init 懒加载 调用getBean的时候再去实例化对象
-
-
-
DI 给对象属性赋值
-
1 通过set方法给对象属性赋值
<!–property 就是在使用set方法实现依赖注入–>
<bean id="user1" class="com.msb.bean.User">
<property name="userid" value="1"></property>
<property name="username" value="张三"></property>
<property name="password" value="abcdefg"></property>
</bean> -
2 通过有参构造给对象属性赋值
<!–
constructor-arg 就是在使用构造方法实现依赖注入
constructor-arg 的个数必须和某个构造方法的参数个数向对应
name 指的是参数名
index 指的是参数的索引
value 指的是参数值
–><bean id="user2" class="com.xxx.bean.User">
<constructor-arg name="userid" value="2"></constructor-arg>
<constructor-arg name="username" value="小明"></constructor-arg>
<constructor-arg name="password" value="123456789"></constructor-arg>
</bean><bean id="user3" class="com.xxx.bean.User">
<constructor-arg index="0" value="3"></constructor-arg>
<constructor-arg index="1" value="小黑"></constructor-arg>
<constructor-arg index="2" value="987654321"></constructor-arg>
</bean> -
3 通过p名称空间和c名称空间给对象属性赋值
-
添加约束
<?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"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> -
配置对象
<!–p名称空间, 就是对property的简化处理–>
<bean id="user4" class="com.xxx.bean.User" p:userid="4" p:username="小东" p:password="111111"></bean><!–c名称空间, 就是对constructor-arg的简化–>
<bean id="user5" class="com.msb.bean.User" c:userid="5" c:username="小西" c:password="222222"></bean> -
测试代码
public class Test1 {
@Test
public void testGetBean() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user1 = context.getBean("user1", User.class);
User user2 = context.getBean("user2", User.class);
User user3 = context.getBean("user3", User.class);
User user4 = context.getBean("user4", User.class);
User user5 = context.getBean("user5", User.class);System.out.println(user1);
System.out.println(user2);
System.out.println(user3);
System.out.println(user4);
System.out.println(user5);
}
} -
输出结果

-
-
4 注入空值和特殊符号
<bean id="user1" class="com.xxx.bean.User">
<!–null值–>
<property name="userid">
<null></null>
</property>
<!–特殊符号 转译字符 < < >> & & –>
<property name="username" value="&xiaoming<>"></property>
<!– 特殊符号 <![CDATA[内容]]> –>
<property name="password">
<value><![CDATA[&<123456>]]></value>
</property>
</bean> -
5 关于bean引用
-
实体类
package com.xxx.bean;
import java.util.Date;
public class Mouse {
private String name;
private Date birthdate;@Override
public String toString() {
return "Mouse{" +
"name='" + name + '\\'' +
", birthdate=" + birthdate +
'}';
}public Mouse() {}
public Mouse(String name, Date birthdate) {
this.name = name;
this.birthdate = birthdate;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public Date getBirthdate() {
return birthdate;
}public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
}package com.xxx.bean;
public class Cat {
private String name;
private Mouse mouse1;@Override
public String toString() {
return "Cat{" +
"name='" + name + '\\'' +
", mouse1=" + mouse1 +
'}';
}public Cat() {}
public Cat(String name, Mouse mouse1) {
this.name = name;
this.mouse1 = mouse1;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public Mouse getMouse1() {
return mouse1;
}public void setMouse1(Mouse mouse1) {
this.mouse1 = mouse1;
}
}-
xml 配置
-
代码详情
<!–告诉容器准备一个Date对象–>
<bean id="date1" class="java.util.Date"></bean><bean id="mouse1" class="com.xxx.bean.Mouse">
<property name="name" value="Jerry"></property>
<!–bean引用引用外部bean–>
<property name="birthdate" ref="date1"></property>
</bean><bean id="cat1" class="com.xxx.bean.Cat">
<property name="name" value="Tom"></property>
<!–引用内部bean–>
<property name="mouse1" >
<bean class="com.xxx.bean.Mouse">
<property name="name" value="Jerry2"></property>
<property name="birthdate">
<bean class="java.util.Date"></bean>
</property>
</bean>
</property>
</bean><bean id="mouse2" class="com.xxx.bean.Mouse"></bean>
<bean id="cat2" class="com.xxx.bean.Cat">
<property name="name" value="Tom2"></property>
<!–级联引入bean–>
<property name="mouse1" ref="mouse2"></property>
<!–用反射调用 get*** 方法,获得对象之后,再赋值–>
<property name="mouse1.name" value="Jerry3"></property>
<property name="mouse1.birthdate">
<bean class="java.util.Date"></bean>
</property>
</bean>
-
-
-
-
6 关于集合注入
-
实体类
package com.xxx.bean;
public class Book {
private String bname;
private String author;@Override
public String toString() {
return "Book{" +
"bname='" + bname + '\\'' +
", author='" + author + '\\'' +
'}';
}public Book() {}
public Book(String bname, String author) {
this.bname = bname;
this.author = author;
}public String getBname() {
return bname;
}public void setBname(String bname) {
this.bname = bname
}public String getAuthor() {
return author;
}public void setAuthor(String author) {
this.author = author;
}
}package com.xxx.bean;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;public class Student {
private String[] books;
private Set<String> bookSet;
private List<String> bookList;
private Map<String,String> bookMap;
private List<Book> bookList2;@Override
public String toString() {
return "Student{" +
"books=" + Arrays.toString(books) +
", bookSet=" + bookSet +
", bookList=" + bookList +
", bookMap=" + bookMap +
", bookList2=" + bookList2 +
'}';
}public String[] getBooks() {
return books;
}public void setBooks(String[] books) {
this.books = books;
}public Set<String> getBookSet() {
return bookSet;
}public void setBookSet(Set<String> bookSet) {
this.bookSet = bookSet;
}public List<String> getBookList() {
return bookList;
}public void setBookList(List<String> bookList) {
this.bookList = bookList;
}public Map<String, String> getBookMap() {
return bookMap;
}public void setBookMap(Map<String, String> bookMap) {
this.bookMap = bookMap;
}public List<Book> getBookList2() {
return bookList2;
}public void setBookList2(List<Book> bookList2) {
this.bookList2 = bookList2;
}public Student() {}
public Student(String[] books, Set<String> bookSet, List<String> bookList, Map<String, String> bookMap, List<Book> bookList2) {
this.books = books;
this.bookSet = bookSet;
this.bookList = bookList;
this.bookMap = bookMap;
this.bookList2 = bookList2;
}
}-
配置文件
<?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"
xmlns:c="http://www.springframework.org/schema/c"
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
">
<!–定义公共集合–>
<util:list id="outerbookList">
<!–声明多个Book对象–>
<bean id="b1" class="com.xxx.bean.Book" p:bname="JAVA" p:author="马士兵"></bean>
<bean id="b2" class="com.xxx.bean.Book" p:bname="Go" p:author="马士兵"></bean>
<bean id="b3" class="com.msb.bean.Book" p:bname="JVM" p:author="马士兵"></bean>
</util:list><bean id="student1" class="com.xxx.bean.Student">
<!–数组属性注入–>
<property name="books">
<array>
<value>JAVA</value>
<value>MySQL</value>
<value>Spring</value>
</array>
</property><!–set集合注入–>
<property name="bookSet">
<set>
<value>JAVA</value>
<value>MySQL</value>
<value>Spring</value>
</set>
</property><!–list集合注入–>
<property name="bookList">
<list>
<value>JAVA</value>
<value>MySQL</value>
<value>Spring</value>
</list>
</property><!–map集合注入–>
<property name="bookMap">
<map>
<entry key="JAVA" value="马士兵"></entry>
<entry key="Go" value="马士兵"></entry>
<entry key="JVM" value="马士兵"></entry>
</map>
</property><!–List对象集合注入–>
<property name="bookList2" ref="outerbookList"></property>
</bean>
</beans>
-
-
-
7 工厂方式获取bean
-
特点
-
bean 标签中定义的 class 类不是返回的对象的类, 而是生产该对象的工厂
-
-
工厂模式
-
GOF 设计模式
-
-
spring 中给我们定义好了一个工厂接口, 可以生产对象的接口, 我们可以通过工厂来获取 bean
-
定义工厂对象 实现 FactoryBean 接口
package com.xxx.bean;
import org.springframework.beans.factory.FactoryBean;
public class BookFactory implements FactoryBean<Book> {
@Override
public Book getObject() throws Exception {
Book book = new Book();
book.setBname("JAVA");
book.setAuthor("xxx");
return book;
}@Override
public Class<?> getObjectType() {
return null;
}
} -
配置文件
<bean id="book" class="com.xxx.bean.BookFactory"></bean>
-
测试代码
@Test
public void testGetBean(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext5.xml");
Book book = applicationContext.getBean("book", Book.class);
System.out.println(book);
}
-
-

