美文网首页Java
深入浅出 Spring 框架,原来以前的都白学了

深入浅出 Spring 框架,原来以前的都白学了

作者: 愿天堂没有BUG | 来源:发表于2022-06-20 17:09 被阅读0次

1. 为啥要用 Spring

张三是一个编程小白,他每次在 service 层写代码都要自己 new 一堆 Dao 接口的实现类。

有一天正 new 着对象,张三心想:"我这一个 service 都需要 new 好多 Dao ,那如果有一堆 service ,那我不得花费好长时间?"

"有没有一个工具类或者什么框架能帮我管理这些对象?我只需要配置一下,需要的时候它就能自动帮我 new 个对象出来?"

张三陷入了深深的沉思之中。

张三的室友李四也是一个编程小白。

李四呢想给自己的小项目增加一个功能:记录方法执行的时间。结果他脑子一热竟然给所有的方法都增加了一堆打印方法:

过了半个小时,李四终于给项目中所有的方法都复制粘贴上了打印语句。他长舒一口气:"我真是个大聪明!"

张三看了一眼李四的代码,连连鼓掌:"妙啊!咱们宿舍的技术大神!"

旁边的王五实在忍不住了,对张三说:"妙个屁!最近的 Spring 框架课你俩是不是都没去?光顾着打游戏了?我都替你俩答了三次到了!"

李四问王五:"这个Spring 框架学了有用吗?"

王五:"不仅能解决张三说的管理对象的问题,还能帮你解决记录日志的问题。配置完 Spring ,你只需要定义一个切面类,根本不需要在一堆类上面复制粘贴一堆代码。"

张三摸摸后脑勺笑着说:"原来 Spring 框架那么好用,我以后再也不逃课了。我这就去翻课本学习 Spring 框架去。"

2. Spring 简介

Spring 是一个轻量级的 Java 开发框架。Spring 的核心是控制反转(IOC)和面向切面编程(AOP)。

Spring 主要有如下优点:

1.解耦

2.支持面向切面编程

3.便于集成其他框架

3. 环境搭建

1.创建 Maven 项目

File -> New -> Project -> Maven

UserServiceImpl

publicclassUserServiceImplimplementsUserService{@Overridepublicvoidprint(){        System.out.println("hello world");    }}

4.创建配置文件

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

5.测试

@TestpublicvoidtestSpring(){// 1、获取工厂ApplicationContext act =newClassPathXmlApplicationContext("/applicationContext.xml");// 2、通过工厂类获得对象UserService userService = (UserService)act.getBean("userService");// 3.调用方法userService.print();}

测试结果:

4. IOC

4.1 IOC 简介

IOC,全称 Inversion of Control,意思是控制反转。它是 Spring 框架中的一种思想。

控制反转就是将对象的控制权从程序中的代码转移到了 Spring 的工厂,通过 Spring 的工厂完成对象的创建以及赋值。

也就是说之前是我们自己 new 对象、给对象中的成员变量赋值。现在是让 Spring 来帮助我们创建对象、给成员变量赋值。

4.2 Spring 核心内容描述

1.配置文件

Spring 的配置文件可以放到项目中的任意一个地方,也可以随意命名,但是建议使用:applicationContext.xml。

你可以将这个配置文件看成一个装有一堆 bean 标签的容器。

2.bean 标签

Spring 工厂创建的对象,叫做 bean,所以一个 bean 标签代表一个对象。

bean 标签中必须要有 class 属性,它的值是一个类的全限定名(包名+类名)。

除了 class 属性,bean 标签还可以设置 id 、name 、scope属性。

id:

id 必须以字母开头,相当于这个 bean 的身份证号,是唯一的。

如果这个 bean 只使用一次,id 可以省略不写。

如果这个 bean 需要被其他 bean 引用,或者这个 bean 要使用很多次,则必须要有 id 属性。

如果只配置 class 属性,Spring 框架会给每一个 bean 配置一个默认的 id:"全限定名#1"。

例如:

com.xxl.service.impl.UserServiceImpl#1

name:

name 相当于这个 bean 的别名,它可以配置多个,例如:

scope:

scope 属性可以控制简单对象的创建次数,它有两个值:

1.singleton:每次只会创建唯一⼀个简单对象,默认值。

2.prototype:每⼀次都会创建新的对象。

例如:

3.ApplicationContext

ApplicationContext 是 Spring 的工厂,主要用来创建对象。

Spring 通过读取配置文件创建工厂。

因为 Spring 的工厂会占用大量内存,所以一个程序一般只会创建一个工厂对象。

4.工厂常用方法

1.根据 id 获取对象

UserServiceuserService = (UserService)act.getBean("userService");

2.根据 id 和类名获取对象

UserService userService = (UserService)act.getBean("userService",UserService.class);

3.只根据类名获取对象

UserService userService = (UserService)act.getBean(UserService.class);

4.获取配置文件中所有 bean 标签的 id 值

String[] beanDefinitionNames = act.getBeanDefinitionNames();for(StringbeanDefinitionName : beanDefinitionNames) {    System.out.println(beanDefinitionName);}

结果:

5.判断是否存在指定 id 或者 name 的 bean

act.containsBean("userService")

6.判断是否存在指定 id 的 bean,只能用来判断 id

act.containsBeanDefinition("userService")

5.创建对象

Spring 是如何创建对象的呢?

工厂和反射

首先说下反射,我们可以通过一个类的全限定名获取 Class 对象,然后再通过 Class 实例化一个对象:

ClassserviceClass = Class.forName("com.xxl.service.impl.UserServiceImpl");UserServiceuserService = (UserService)serviceClass.newInstance();

Spring 配置文件中 bean 标签的 id 和类的全限定名一一对应,所以 Spring 工厂的 getBean 方法其实就是先根据 bean 的 id 获取该类的全限定名,然后再利用反射根据类的全限定名创建对象并返回。

4.3 IOC 优点

解耦

说起解耦之前先说下耦合:耦合是指代码之间的关联性太强,我如果改了这一段代码,可能会影响到一堆代码。

那创建对象哪里有耦合了?其实就是new关键字带来的耦合。

如果你发现一个接口的实现类需要修改,你需要手动改动程序中的代码,比如修改 new 关键字后面的实现类,这样可能会影响到其他的代码。

但是使用了 Spring 之后,我们只需要修改配置文件中 bean 标签的 class 属性对应的类的全限定名,不用修改程序中的代码,这样就做到了解耦。

解耦就是解除不同代码之间的关联性、依赖性。

5. DI

DI 全称 Dependency Injection,意思是依赖注入,它是 IOC 的具体实现。

依赖就是说我需要你,比如 Service 层依赖 Dao 层,注入就是赋值

依赖注入:使用 Spring 的工厂和配置文件为一个类的成员变量赋值。

没有使用 Spring 的依赖注入我们是这样赋值的:

User user =newUser();user.setName("张三");

如果设置有误,就需要手动修改代码,代码耦合度较高,而依赖注入的出现就是为了解耦。

Spring 的依赖注入包含两种方式:

5.1 set 注入

set 注入:Spring 调用 Set 方法通过配置文件为成员变量赋值。

1.创建对象,为属性添加 set/get 方法

publicclassUser{privateString name;privateintage;publicStringgetName(){returnname;    }publicvoidsetName(String name){this.name = name;    }publicintgetAge(){returnage;    }publicvoidsetAge(intage){this.age = age;    }}

2.修改配置文件

3.测试

// 1、获取工厂ApplicationContext act =newClassPathXmlApplicationContext("/applicationContext.xml");// 2、通过工厂类获得对象User user = (User)act.getBean("user");System.out.println("姓名:"+user.getName());System.out.println("性别:"+user.getAge());

测试结果:

从上面的例子可以看出 Set 注入就是在 property 标签中为属性赋值。spring 可以为 JDK 内置的数据类型进行赋值,也可以为用户自定义的数据类型进行赋值。

5.1.1 JDK 内置数据类型

1.基本类型

2.List 集合

157999999181578888881915766666620

3.Set 集合

157999999181578888881915766666620

4.Map 集合

name知否君age23

5.数组

157999999181578888881915766666620

6.Properites

value1value2

5.1.2 用户自定义数据类型

1.为成员变量添加 set/get 方法

publicclassUserServiceImplimplementsUserService{privateUserDao userDao;publicUserDaogetUserDao(){returnuserDao;    }publicvoidsetUserDao(UserDao userDao){this.userDao = userDao;    }@Overridepublicvoidprint(){        userDao.print();    }}

2.bean 标签使用 ref 属性

 

3.测试

@TestpublicvoidtestSpring(){// 1、获取工厂ApplicationContext act =newClassPathXmlApplicationContext("/applicationContext.xml");// 2、通过工厂类获得对象UserService userService = (UserService)act.getBean("userService");// 3.调用方法userService.print();}

测试结果:

解释:

上面的例子中,因为 userDao 是 userService 的一个成员变量,所以在配置文件中需要使用 property 标签,ref 指向了 userDao 这个对象,然后调用 userDao 的 set 方法为 userDao 赋值。

4.自动注入

我们还可以使用 bean 标签的 autowire 属性为自定义变量自动赋值。当类中引用类型的属性名和 bean 标签的 id 值相同时,我们可以使用 byName。例如:

当类中引用类型的全限定名和 bean 标签的 class 属性的值相同,或者是子类、实现类,我们可以使用 byType。例如:

5.2 构造注入

构造注入:Spring 调用构造方法通过配置文件为成员变量赋值。

1.为类添加构造方法

publicclassUser{privateString name;privateintage;publicUser(String name,intage){this.name = name;this.age = age;    }publicStringgetName(){returnname;    }publicvoidsetName(String name){this.name = name;    }publicintgetAge(){returnage;    }publicvoidsetAge(intage){this.age = age;    }}

2.修改配置文件

在 bean 标签中使用 constructor-arg 标签。

3.测试

@TestpublicvoidtestSpring(){// 1、获取工厂ApplicationContext act =newClassPathXmlApplicationContext("/applicationContext.xml");// 2、通过工厂类获得对象User user= (User)act.getBean(User.class);    System.out.println("姓名:"+user.getName());    System.out.println("年龄:"+user.getAge());}

测试结果:

5.3 注入总结

注入就是通过 Spring 的配置文件为类的成员变量赋值。在实际开发中,我们一般采用 Set 方式为成员变量赋值。

相关文章

网友评论

    本文标题:深入浅出 Spring 框架,原来以前的都白学了

    本文链接:https://www.haomeiwen.com/subject/kbujvrtx.html