本篇文章为你整理了Spring学习笔记(spring教程 csdn)的详细内容,包含有spring入门教程 spring教程 csdn spring详细教程 spring 教程 Spring学习笔记,希望能帮助你了解 Spring学习笔记。
官网:https://spring.io
2.1.1 Spring能做的工作
......
2.1.2 重点学习的内容
Spring Framework:是Spring中最早最核心的技术,也是所有其他技术的基础。
SpringBoot:简化开发,而SpringBoot是来帮助Spring在简化的基础上能更快速进行开发。
SpringCloud:用来做分布式之微服务架构的相关开发。
SpringData、SpringSecurity 等目前也是流行的技术
2.1.3 Spring发展史
随着时间推移,版本不断更新维护,目前最新的是Spring5
Spring1.0是纯配置文件开发
Spring2.0为了简化开发引入了注解开发,此时是配置文件加注解的开发方式
Spring3.0已经可以进行纯注解开发,使开发效率大幅提升
Spring4.0根据JDK的版本升级对个别API进行了调整
Spring5.0已经全面支持JDK8,现在Spring最新的是5系列
2.2 Spring系统架构
2.2.1 系统架构及其图示
AOP :面向切面编程,它依赖核心层容器,目的是在不改变原有代码的前提下对其进行功能增强
Aspects :AOP是思想,Aspects是对AOP思想的具体实现
Data Access :数据访问,Spring全家桶中有对数据访问的具体实现技术
Data Integration :数据集成,Spring支持整合其他的数据层解决方案,比如Mybatis
Transactions :事务,Spring中事务管理是Spring AOP的一个具体实现,将在后续内容中详细说明
如:Dao层更改了内容,将使用新的函数进行数据处理,此时Service层也要修改,并且需要重新编译
IOC(Inversion of Control)控制反转:使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想(对象的创建控制权的转移)称为控制反转。
Bean:IOC容器负责对象的创建、初始化等一系列工作(其中包含了数据层和业务层的类对象),被创建或被管理的对象在IOC容器中都被成为称为Bean对象
DI(Dependency Injection)依赖注入:IoC容器为了解决Bean对象之间的依赖关系而自动建立bean对象绑定的过程
如:Service需要依赖Dao,IoC容器会将两个bean对象进行绑定
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save() {
System.out.println("book service save ...");
bookDao.save();
import priv.dandelion.service.BookService;
import priv.dandelion.service.Impl.BookServiceImpl;
public class App {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
bookService.save();
* 控制台输出:
* book service save ...
* book dao save ...
在resources目录下添加Spring配置文件:applicationContext.xml,在配置文件中完成bean的配置
?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 : 给Bean命名
class : 给Bean定义类型
bean id="bookDao" /
bean id="bookService" /
/beans
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import priv.dandelion.service.BookService;
public class App2 {
public static void main(String[] args) {
// 获取IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取Bean
BookService bookService = (BookService) context.getBean("bookService");
bookService.save();
* 控制台输出:
* book service save ...
* book dao save ...
修改被依赖类的成员属性中创建对象部分,并为其添加set方法
package priv.dandelion.service.Impl;
import priv.dandelion.dao.BookDao;
import priv.dandelion.service.BookService;
public class BookServiceImpl implements BookService {
// 删除业务层中使用new的方式创建的dao对象
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
// 提供所要创建成员对象的对应的set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
?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 : 给Bean命名
class : 给Bean定义类型
bean id="bookDao" /
bean id="bookService"
!-- 配置Service 与Dao的关系--
property标签 : 表示配置当前Bean的属性
name属性 : 表示配置参照哪一个具体的属性名称,注意需要实现其set方法
ref属性 : 表示参照(引用)哪一个Bean
property name="bookDao" ref="bookDao"/
/bean
/beans
id:bean 的 id ,使用容器可以通过 id 值获取对应的 bean ,在一个容器中id唯一
class:bean 的类型,即配置的 bean 的全路径名 (不能是接口,接口不能实例化)
bean 的 ref 属性可以参照(引用)对应 bean 的 name 属性值,不过建议还是引用 id,保持一致
!--
id : 给Bean命名
class : 给Bean定义类型
bean id="bookDao" name="dao" /
bean id="bookService" name="service,service2 bookEbi"
!-- 配置Service 与Dao的关系--
property标签 : 表示配置当前Bean的属性
name属性 : 表示配置参照哪一个具体的属性名称,注意需要实现其set方法
ref属性 : 表示参照(引用)哪一个Bean
property name="bookDao" ref="dao"/
/bean
!-- bookDao 配置了属性 scope="prototype" --
bean id="bookDao" scope="prototype"/
bean id="bookService" name="service,service2 bookEbi"
property name="bookDao" ref="bookDao"/
/bean
执行
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 单例
BookService bookService1 = (BookService) context.getBean("service");
BookService bookService2 = (BookService) context.getBean("service");
System.out.println(bookService1); // priv.dandelion.service.Impl.BookServiceImpl@25bbe1b6
System.out.println(bookService2); // priv.dandelion.service.Impl.BookServiceImpl@25bbe1b6
// 非单例
BookDao bookDao1 = (BookDao) context.getBean("bookDao");
BookDao bookDao2 = (BookDao) context.getBean("bookDao");
System.out.println(bookDao1); // priv.dandelion.dao.Impl.BookDaoImpl@5702b3b1
System.out.println(bookDao2); // priv.dandelion.dao.Impl.BookDaoImpl@69ea3742
定义 bean 的作用范围,默认为单例(默认单例,节约资源),可进行配置
* singletion:单例
* prototype:非单例
bean 的本质就是对象,创建 bean 使用无参构造方法完成(底层采用暴力反射)
bean的三种实例化方法:
// 验证:bean的实例化本质上是调用了无参构造方法,手动实现并在控制台输出内容
// 验证:底层使用暴力反射机制,当构造方法使用private时,也不会影响bean的实例化
private BookDaoImpl() {
System.out.println("book dao constructor is running ....");
public void save() {
System.out.println("book dao save ...");
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
* 控制台输出:
* book dao constructor is running ....
* book dao save ...
* Process finished with exit code 0
使用工厂方式创建对象,在一定程度上进行解耦,但不如将工厂交给Spring来管理(见4.2.3.2)
!-- property标签 : 表示配置当前Bean的属性 --
!-- class属性 : 所使用的工厂的全类名 --
!-- factory-method属性 : 工厂中创建bean的方法名 --
bean id="orderDao" factory-method="getOrderDao"/
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");
orderDao.save();
* 控制台输出:
* factory setup....
* order dao save ...
!-- 指定工厂,并使用工厂对应方法获取所需的bean对象 --
!-- factory-bean:指定工厂bean --
bean id="userDao" factory-bean="userFactory" factory-method="getUserDao"/
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) ctx.getBean("userDao");
userDao.save();
* 控制台输出:
* user dao save ...
工厂的bean对象只是为了配合使用,毫无意义
对于每个需要的bean,其中factory-method属性值不固定,每次都需要配置
使用FactoryBean对其进行改进
FactoryBean 工厂类
// FactoryBean创建对象,需要实现FactoryBean T 接口并指定泛型
public class UserDaoFactoryBean implements FactoryBean UserDao {
// 代替原始实例工厂中创建对象的方法
public UserDao getObject() throws Exception {
return new UserDaoImpl();
// 指定Object的类型,返回对应的类的字节码文件
public Class ? getObjectType() {
return UserDao.class;
// 创建出的 bean 是否为单例,返回 true 为单例,不覆写该方法时默认为为单例
public boolean isSingleton() {
return true;
!-- bean id="userFactory" / --
!-- bean id="userDao" factory-bean="userFactory" factory-method="getUserDao"/ --
bean id="userDao" /
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
* book dao save ...
!--init-method:设置bean初始化生命周期回调函数--
!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象--
bean id="bookDao" init-method="init" destroy-method="destroy"/ bean id="bookDao" init-method="init" destroy-method="destroy"/
如运行情况中所示,控制台没有输出destroy...,说明销毁方法未被执行,该问题将在 4.3.3 和 4.3.4 得到解决
/**
* init...
* book dao save ...
原因:程序运行结束时,JVM虚拟机直接被关闭,销毁方法来不及执行
解决方案:在关闭JVM虚拟机之前手动关闭容器,可以执行销毁方法
存在问题:ApplicationContext中没有实现close()
解决方案:其实现类ClassPathXmlApplicationContext对其进行了实现
public class AppForLifeCycle {
public static void main( String[] args ) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//关闭容器
ctx.close();
* init...
* book dao save ...
* destroy...
close关闭容器相对而言比较暴力,如果在 close 之后还有未执行的语句,可能会发生问题
注册钩子关闭容器语句可以写在任何位置,且仅在JVM虚拟机关闭前执行销毁
//注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
ctx.registerShutdownHook();
核心配置文件(不需要写 init-method 和 destroy-method 属性)
bean id="bookService"
property name="bookDao" ref="bookDao"/
/bean
Service
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
System.out.println("set .....");
this.bookDao = bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
public void destroy() throws Exception {
System.out.println("service destroy");
// 如方法名所述,该方法运行在set方法之后
public void afterPropertiesSet() throws Exception {
System.out.println("service init");
public static void main( String[] args ) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
ctx.registerShutdownHook();
* init...
* set .....
* service init
* book dao save ...
* service destroy
* destroy...
类中给出成员变量并实现其setter
public class BookServiceImpl implements BookService {
private BookDao bookDao;
private UserDao userDao;
//setter注入需要提供要注入对象的set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
//setter注入需要提供要注入对象的set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
userDao.save();
!--property标签:设置注入属性--
!--name属性:设置注入的属性名,实际是set方法对应的名称--
!--ref属性:设置注入引用类型bean的id或name--
property name="bookDao" ref="bookDao"/
property name="userDao" ref="userDao"/
/bean
在类中定义成员变量并实现其 setter
public class BookDaoImpl implements BookDao {
private String databaseName;
private int connectionNum;
//setter注入需要提供要注入对象的set方法
public void setConnectionNum(int connectionNum) {
this.connectionNum = connectionNum;
//setter注入需要提供要注入对象的set方法
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
public void save() {
System.out.println("book dao save ..."+databaseName+","+connectionNum);
!--property标签:设置注入属性--
!--name属性:设置注入的属性名,实际是set方法对应的名称--
!--value属性:设置注入简单类型数据值,Spring内部会自动进行类型转换--
property name="connectionNum" value="100"/
property name="databaseName" value="mysql"/
/bean
类中给出成员变量并使用有参构造对需要注入的成员进行初始化操作
public class BookServiceImpl implements BookService {
private BookDao bookDao;
private UserDao userDao;
public BookServiceImpl(BookDao bookDao, UserDao userDao) {
this.bookDao = bookDao;
this.userDao = userDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
userDao.save();
!-- 注意此处的 ref 属性值为:构造方法的形参名 --
constructor-arg name="userDao" ref="userDao"/
constructor-arg name="bookDao" ref="bookDao"/
/bean
类中给出成员变量并使用有参构造对需要注入的成员进行初始化操作
public class BookDaoImpl implements BookDao {
private String databaseName;
private int connectionNum;
public BookDaoImpl(String databaseName, int connectionNum) {
this.databaseName = databaseName;
this.connectionNum = connectionNum;
public void save() {
System.out.println("book dao save ..."+databaseName+","+connectionNum);
constructor-arg name="connectionNum" value="10"/
constructor-arg name="databaseName" value="mysql"/
/bean
5.2.3 【补充】不同场景构造器注入简单数据类型的其他写法 —— 用于解耦
!-- 1. 标准书写 --
bean id="bookDao"
constructor-arg name="connectionNum" value="10"/
constructor-arg name="databaseName" value="mysql"/
/bean
!-- 2. 解决形参名称的问题,与形参名不耦合 --
bean id="bookDao"
constructor-arg type="int" value="10"/
constructor-arg type="java.lang.String" value="mysql"/
/bean
!-- 3. 解决参数类型重复问题,使用位置解决参数匹配 --
bean id="bookDao"
constructor-arg index="0" value="mysql"/
constructor-arg index="1" value="100"/
/bean
5.3 自动配置
IoC 容器根据 bean 所依赖的资源在容器中自动查找并注入到 bean 中的过程称为自动装配
自动装配用于引用类型依赖注入,不能对简单类型进行操作
使用按类型装配时(byType)必须保障容器中相同类型(class)的 bean 唯一,推荐使用
使用按名称装配时(byName)必须保障容器中具有指定名称(id)的 bean,因变量名与配置耦合,不推荐使用
自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
被注入的 bean 所在的类必须实现 setter
被注入的 bean(按照全类名,即 class 属性)有且仅有一个
按类型注入时,被注入的 bean 可以没有 id
被注入的 bean 所在的类必须实现 setter
被注入的 bean 的 id 属性必须和类中的成员名称,准确说是 setter 名称保持一致,否则会给一个空对象,导致空指针异常
变量名与配置耦合
?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="bookDao"
!--数组注入--
property name="array"
array
value 100 /value
value 200 /value
value 300 /value
/array
/property
!--list集合注入--
property name="list"
list
value dande /value
value dandel /value
value dandelio /value
value dandelion /value
/list
/property
!--set集合注入--
property name="set"
set
value dande /value
value dandel /value
value dandelio /value
value dandelio /value
/set
/property
!--map集合注入--
property name="map"
map
entry key="country" value="china"/
entry key="province" value="henan"/
entry key="city" value="kaifeng"/
/map
/property
!--Properties注入--
property name="properties"
props
prop key="country" china /prop
prop key="province" henan /prop
prop key="city" kaifeng /prop
/props
/property
/bean
/beans
public static void main( String[] args ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
* book priv.dandelion.dao save ...
* 遍历数组:[100, 200, 300]
* 遍历List[dande, dandel, dandelio, dandelion]
* 遍历Set[dande, dandel, dandelio]
* 遍历Map{country=china, province=henan, city=kaifeng}
* 遍历Properties{province=henan, city=kaifeng, country=china}
以上就是Spring学习笔记(spring教程 csdn)的详细内容,想要了解更多 Spring学习笔记的内容,请持续关注盛行IT软件开发工作室。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。