前言 (SpringBoot vs Servlet)
1.1 为什么要学习框架?
学习框架的目的在于升级,我们从亲力亲为到组件装配,框架更加易用、简单且高效。
1.2 使用SpringBoot 项目演示框架对比Servlet有很多优点
1.不需要配置Tomcat,一键运行项目,内置Web容器,可直接运行;
2.快速添加外部jar包,不易出错;
3.快速发布项目,无需配置Tomcat;
4.对象自动装配……
在我们使用Servlet的时候,可以体会到很多不便,这些不便在我们框架中得到了对应的解决,使用感受相对来说会更好一些。
1.3 如何学习框架?
基础框架Spring→SpringBoot快速开发Spring脚手架→MyBatis快速操作数据库→……
什么是Spring
2.1 Spring( Spring Framework(Spring 框架))
Spring是一个开源框架,有非常活跃和庞大的社区支持,Spring支持广泛的应用场景,可以让Java企业级开发更简单。简单来说Spring 是包含众多工具方法的 IoC 容器。也就是说 Spring 最核心的功能就是容器管理。在 Spring 框架中也有很多模块,如 Spring JDBC 、Spring MVC 、Spring Security、 Spring AOP 、Spring ORM 、Spring Test 等,我们通过使用这些模块可以大幅度的提升开发效率。
2.2 Ioc(Inversion of Control)
Spring是一个IoC容器。对象的实例不再由调用者来创建,而是由容器来创建,容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由应用代码转移带了容器,控制权发生了反转,这就是控制反转。它是spring框架的核心思想之一。
2.3 DI(Dependency Injection)
中文中是“依赖注入”的意思,当某个java 实例需要另一个java实例时,创建被调用者的工作不是由调用者实现,而是由spring容器来完成,然后注入调用者,因此称为依赖注入。
2.4 IoC和DI的区别
IoC和DI是同一概念的不同角度描述,具体来讲,IoC 是“目标”也是一种思想,而目标和思想只是一种指导原则,最终还是要有可行的落地方案,而 DI 就属于具体的实现。
传统程序开发 VS 控制反转程序开发
3.1 传统程序开发
传统程序的开发就比如建一座房子,房顶依赖墙体,墙体依赖房梁,房梁依赖地基。建筑这样一座房子,地基的大小是先进行固定的,如果低级一旦发生变动,那么其余的全部进行修改甚至推翻重来。这样的程序问题就存在于当底层代码改动之后,整个调用链上的所有代码都需要进行修改。然而我们在开发过程中肯定不想一直做返工活,针对这种缺陷做出改变,就有了控制反转程序开发方式。
3.2 控制反转程序开发
控制反转程序开发方式对传统程序开发中类创建的缺陷进行解决,我们不在每个类中创建自己的下级,而是将原来由自己创建的下级类改为注入方式,把下级对象注入到当前对象中,不需要在当前类中创建下级类,因此即使下级类发生改变,当前类也不需要做出任何改变,这就完成了程序的解耦,在程序开发中,低耦合高内聚是判断程序好坏的标准之一。
Spring创建和使用
Spring创建项目创建步骤:
1.创建一个maven项目
2.在pom.xml中添加Spring框架支持
3.创建启动类包含main方法
注! maven项目相关配置:
1.在idea这两处都需要进行配置,配置的内容是一样的
2.以当前项目配置为例
3.settings.xml配置 如果上图中settings file有该文件,则只需要进行配置国内源,如果没有则需要加上该文件并进行相关配置。
Spring读取和存储对象
学习Spring关键就在于将对象存⼊到 Spring 中,再从 Spring 中获取对象的过程。
5.1 存储Bean对象
Bean就是Java中的一个普通对象
1.创建Bean对象
2.在resource下创建Spring配置文件
Spring配置文件:
<?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:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<content:component-scan base-package="com.bit.service"></content:component-scan>
</beans>
这个.xml文件是用来告诉Spring框架需要干什么
3.将Bean对象存储到Spring配置文件中
其中id是Bean对象名称,不能重复,类似于域名,class是对象本身,包括包名和类名,类似于IP
5.2 读取Bean对象
1.得到Spring对象
2.通过Spring对象获取某个指定的Bean对象
第一种方法由于根据Bean名称来获取Bean,需要对Bean类型进行强转,也存在一定问题。
这里的user要和上面的id一一对应
其余方法:
第二种方法可以解决没有id情况下,根据Bean类型来获取Bean,但是当同一个类型注入到xml多次时,类型一致,就发生冲突了,不建议使用,后患无穷。
第三种方法根据名称加类型来获取Bean,这就解决了第一个和第二个方法存在的问题,这是使用最常见的一种方式。
3.使用Bean对象
这是一个可选项,可以选择打印User下的方法的响应
5.3 ApplicationContext VS BeanFactory
相同点:
都可以得到Spring上下文对象;都来自Spring顶层接口。
不同点:
功能上:前者是继承后者的,是后者的子类,后者只有最基础访问Bean的能力,前者拥有后者所有的功能并且有后者没有的功能。
性能上:前者是一次性加载并初始化所有Bean对象,后者是用一个加载一个,因此前者比后者快。
注解
上面在存储Bean对象时,需要在xml文件中一行一行进行添加,操作起来比较麻烦,而注解可以解决这种不便。
6.1 前置工作
在引号里面写入需要将Bean对象存储到Spring中的根目录,例如:
6.2 添加注解存储Bean对象
6.2.1 五大类注解
@Controller:控制器
在这里获取对象需要将类名首字母进行小写。存在以下问题:
问题一:如果类名首字母是小写,那么获取对象的时候,仍是将类名首字母小写
问题二:如果类名首字母和的第二个字母都是大写,当使用默认规则首字母小写获取Bean对象时,出现了错误;正确获取Bean对象的方法是使用原类名。
结论:当使用五大类注解时,默认情况下获取Bean对象,只需要将类名首字母小写即可,当Bean对象首字母和第二个字母均为大写时,需要用原类名获取Bean对象。
这个结论属于Spring约定。在Spring中约定大于配置,故我们只需要按照要求来操作即可。
问题三:当所有类都写在java根路径下的时候,读取根路径及根路径下的所有目录,最好的方法是给项目创建目录。
@Component:组件
@Service:服务
@Repository:仓库
@Configuration:配置
以上类注解用法类似,存在五个类注解是为了便于了解类注解的用途,更加直观清楚。其功能有细微的不同。
五大类注解的用途:
1.控制器:归属于业务逻辑层,用来控制用户的行为,用来检查用户参数的有效性。
2.组件:归属于公共工具类,提供某些公共方法。
3.服务:归属于服务层,调用持久化类实现相应的功能。不直接和数据库交互,类似于控制中心。
4.仓库:归属于持久层,是直接和仓库进行交互的。通常每一个表都会对应一个@Repository。
5.配置:归属于配置层,用于配置当前项目的所有信息。
五大类注解有什么关系:
@Component是@Controller、@Service、@Repository、@Configuration的父类。
6.2.2 方法注解
@Bean:将当前修饰方法的方法对象存储到Spring当中
注意:@Bean必须配合五大类注解同时使用,否则是无效的方法注解。
6.3 从Spring中更简单获取Bean对象
6.3.1 属性注入
Spring框架赋值和程序自己赋值的效果是相同的。
优点:实现简单
缺点:
1.功能性问题:无法注入一个不可变的对象(final修饰的对象);
2.通用性问题:只能适应于IoC容器;
3.设计原则问题:更容易违背单一设计原则(针对对象是类)。
6.3.2 构造方法注入
当一个类中只有一个构造方法时,可以省略@Autowired
优点:
1.可以注入一个不可变的对象
2.注入的对象不会被修改
①加了final修饰符
②构造方法是随着类加载只执行一次的(不像set有可能被执行多次修改的风险)。
3.注入的对象会被完全初始化(使用构造方法带来的优点)。
4.通用性更好。
因此从Spring 4.x之后,Spring官方推荐使用构造方法注入的形式。
缺点:没有属性注入实现简单。
6.3.3 Setter注入
优点:更加符合单一设计原则(针对对象方法级别)。
缺点:
1.不能注入不可变对象;
2.注入的对象可被修改(set方法是普通set方法,可以被重复调用,在被调用时存在被修改的风险)。
单一设计原则:针对类级别;针对方法级别。
6.3.4小结
日常开发中使用属性注入实现更简单的读取Bean,依然是主流的实现方式。
Spring的注入方式也是常见的面试问题:Spring有哪几种注入方式?它们有什么区别?
6.3.5 @Resource:另一种注入关键字
使用@Resource依然可以实现获取Bean
@Autowired VS @Resource :
相同点:都是用来实现依赖注入的
不同点:
1.功能支持不同:@Autowired支持属性注入、setter注入和构造方法注入;@Resource支持属性、setter注入,但不支持构造方法注入。
2.出身不同:@Autowired来自Spring框架;而@Resource来自JDK;
3.参数支持不同:@Resource支持更多的参数设置;@Autowired 只支持required参数。