为什么要学Spirng?
1、Spring技术是JavaEE开发必备技能,企业开发都在用。
2、能够简化开发,整合框架,提升开发效率。其中核心技术为AOC,AOP,事务处理。
Spring Framework是Spring生态圈最基础的项目,是其他项目的根基。
Spring 4.x系列架构图如下:

● Core Container:架构的最底层结构,核心,容器包含的是对象
● AOP:面向切面编程,不惊动原始程序的情况下,增加功能,依赖于底层结构
● Aspects:AOP思想实现,由于效果卓越被整合到了Spirng框架中
● Data Access:数据访问
● Data Integration:数据集成,Spring内部不仅提供了自己访问对象的技术,同时支持与其他技术整合使用,其中的Transactions(事务)需重点学习
● Web:Web,在SpringMVC中重点学习
● Test:单元测试与集成测试,主要学习单元测试内容
学习顺序:Core Container → Data Access/Integration → AOP/Aspects → Transactions

这部分内容主要包含IoC/DI、IoC容器和Bean。
IoC是什么?
现如今代码编写中遇到的问题

业务层需要调用数据层的方法,就需要在业务层new数据层的对象,如果数据层的实现类发生变化,那么业务层代码也需要改变,发生变化后,都需要进行编译打包和重新部署
所以现如今代码编写过程的问题是耦合度偏高
如何解决这个问题呢?假如不用new数据层的对象,那么依赖便可以降低,但是此时代码逻辑无法运行

因此Spring提出了一个解决方法:
使用对象时,在程序中不要主动new对象,转而由外部提供对象
IoC(Inversion of Control):控制反转
● 对象的创建控制权由程序转移到外部,这种思想称为控制反转
● Spring技术对IoC思想进行了实现,Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的“外部”
● IoC容器负责对象的创建,初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
在IoC中创建了多个Bean对象,但是此时代码仍不能正常运行,因为在业务层,Service是依赖于dao对象运行的,现在只是在外部创建了对象,但不同的对象之间没有联系

DI(Dependency Injection):依赖注入
● 在容器中建立bean和bean之间的依赖关系的整个过程,称为依赖注入
所以,这套流程下来的目的只有一个,就是充分解耦
● 使用IoC容器管理Bean(IoC)
● 在IoC容器中将有依赖关系的bean进行关系绑定(DI)
最终实现:
使用对象时不仅可以直接从IoC容器中获取,而且获取到的bean已经绑定了所有依赖关系
IoC入门案例思路分析
1.管理什么?(Service和Dao)
2.如何将被管理的对象告知IoC容器?(配置)
3.被管理的对象交给IoC容器,如何获取到IoC容器?(接口)
4.IoC容器得到后,如何从容器中获取bean?(接口方法)
5.使用Spring导入哪些坐标?(pro.xml)
需求分析:将BookServiceImpl和BookDaoImpl交给Spring管理,并从容器中获取对应的bean方法进行方法调用
1.创建Maven的java项目
2.pro.xml添加Spring的依赖jar包
3.创建BookService,BookServiceImpl,BookDao,BookDaoImpl四个类
4.resources下添加spring配置文件,并完成bean的配置
5.使用Spring提供的接口完成IoC容器的创建
6.从容器中获取对象进行方法调用
步骤一:创建Maven项目,目录结构如下

步骤2:pro.xml添加Spring的依赖jar包,需要提前配置好Maven

步骤3:添加案例中的实现类和接口类


步骤4:resources下添加spring配置文件,并完成bean的配置(resources下创建xml文件)

步骤5、6:使用Spring提供的接口完成IoC容器的创建,并完成对象的获取

获取结果如下:

为什么会输出两条呢,因为在BookServiceImpl类中,我们new了一个BookDaoImpl的对象

所以解耦不完全,需要学习DI(依赖注入)的相关知识才能解耦完全。
DI入门案例思路分析
1、基于IoC管理bean
2、Service中使用new形式创建的Dao对象是否保留(否)
3、Service中需要的Dao对象如何进入Service中?(提供方法)
4、Service与Dao间的关系如何描述?(配置)
步骤1:删除BookServiceImpl类中创建的Dao对象

步骤2:提供依赖对象对应的setter方法(这个方法是容器在调用)
这种方式称为Setter注入:将类所依赖的对象传递给类,而不是在类内部自己创建对象

步骤3:在xml文件中配置service与dao之间的关系



在xml文件中添加bean别名,程序仍可正常运行

bean作用范围
为了节省资源,默认为单例

也就是说,创建多个bean,实际上地址值都是相同的

适合交给Spring 容器进行管理的bean
● 表现层对象
● 业务层对象
● 数据层对象
● 工具对象
不适合交给Spring 容器进行管理的bean
● 封装实体的域对象 (有具体参数的)
那么单例bean是如何创建出来的呢?
共有三种方式
构造方法(常用)
bean本质上发就是对象,创建bean使用构造方法完成
与上述类似,用bean创建一个BookDaoImpl实现BookDao接口。
运行结果如下: 
现在在BookDaoImpl类中创建一个空参的构造方法,创建BookDao的 bean,也就是说需要创建BookDaoImpl实现类对象,必须实现空参构造方法,我们提供了空参构造方法,并将权限改为private

重新运行程序

发现即使在类内使用了private关键字修饰空参构造方法,依然可以创建实现类BookDaoImpl的对象,说明bean对象的构建是采用了反射的方法。(暴力反射)
如果我们给构造方法加入参数,发现报错了,说明Spring创建bean时候默认调用的是无参的构造方法(反射默认调用的也是无参的构造方法)

注:系统默认调用无参构造方法构建对象,如果我们提供了有参构造,但是没有提供无参构造方法,将抛出异常 BeanCreationException
静态工厂(了解)
创建一个OrderDaoImpl实现类,实现OrderDao接口,并通过静态工厂创建对象。如图所示:

运行结果如下:

那么如何在工厂模式下,构造bean对象呢
首先需要在 applicationContext.xml 内实例化bean,class构建的factory的实例化对象,显然这不是我们想要的,我们真正想要的是在factory类中方法返回的OrderDaoImpl实例化对象,所以需要在实例化bean时添加factory-method属性,最后修改测试类,用bean方式构造对象。修改如图所示:

实例工厂
创建UserDaoImpl实现UserDao接口,在工厂中利用实例工厂创建对象,注意此时并不是静态的变量,所以在测试类中需要创建实例工厂对象,通过对象调用方法,如图所示:

运行结果如下:

在实例工厂模式下构造bean对象,在applicationContext.xml中修改
区别于静态工厂,实例工厂构建bean对象,需要首先将工厂的bean对象构建出来,然后再构建实现类的bean对象,并且指定工厂类中的方法

运行结果

写完我们发现,首先工厂bean只是为了配合实现类对象构建bean,本身没什么意义,另外factory-method 方法名不固定,每次都需要配置,因此Spring针对第三种实例工厂进行了优化。
FactoryBean(第三种变种 重要)
我们在工厂下创建一个全新类,名为UserDaoFactoryBean,该类需要实现一个FactoryBean接口,接口需要提供一个泛型,需要造什么对象就提供什么泛型。然后重写接口中的两个方法。
方法一:代替原始实例工厂创建对象的方法
方法二:提供创建类型的class文件

接下里我们配置bean并运行

在这个FactoryBean接口中还定义了方法isSingleton,用来更改bean是单例还是非单例的,返回true为单例,false为非单例(bean默认单例)

● 生命周期:从创建到消亡的完整过程
● bean生命周期:bean从创建到销毁的整体过程
● bean生命周期控制:在bean创建后到销毁前做一些事情
实例:首先创建一个新的工程文件如下图所示

生命周期主要在两部分:首先是bean创建后,其次是bean消亡前。我们依次在BookDaoImpl类中定义方法

然后在配置文件中配置

运行结果为:

为什么init方法执行了,destroy方法没有执行呢?因为程序是运行在java虚拟机中,程序运行完毕直接关闭了并没有给destroy运行的机会,我们可以在程序中手动关闭容器,调用实现类ClassPathXmlApplicationContext中的 close() 方法,关闭容器

再次运行程序:

另外我们可以通过关闭钩子来关闭容器,关闭钩子用于在JVM正常关闭时,能够先关闭Spring容器,与上述得到的效果一样。写法如下:

这两种方法的区别就是,close方法比较暴力,代码只能放在最后面,不然程序无法正常运行,而关闭钩子可以放在任意位置。
我们也可以通过接口来完成生命周期的控制,好处是不用再配置init-method和destroy-method
修改BookServiceImpl类,添加两个接口 InitializingBean, DisposableBean 并实现接口的两个方法

更改相关代码

运行结果如下:

Bean生命周期小结:
(1)关于Spring中对bean生命周期控制提供了两种方式:
- 在配置文件中的bean标签中添加和属性
- 类实现与接口,这种方式了解下即可。
(2)对于bean的生命周期控制在bean的整个生命周期中所处的位置如下:
- 初始化容器
- 1.创建对象(内存分配)
- 2.执行构造方法
- 3.执行属性注入(set操作)
- ==4.执行bean初始化方法==
- 使用bean
- 1.执行业务操作
- 关闭/销毁容器
- ==1.执行bean销毁方法==
(3)关闭容器的两种方式:
- ConfigurableApplicationContext是ApplicationContext的子类
- close()方法
- registerShutdownHook()方法
● 普通方法(set方法)
● 构造方法
思考:依赖注入描述了在容器中建立了bean和bean之间依赖关系的过程,如果bean运行需要的是数字或字符串呢?
● 引用类型
● 简单类型(基本数据类型与String)
依赖注入方式
● setter注入
● 简单类型
● 引用类型
● 构造器注入
● 简单类型
● 引用类型
此处创一个新的Maven项目,目录如下:

文件的具体内容如下,与之前项目相似的配置


以及在测试程序中的内容

setter注入
引用类型:
我们之前已经见过多次,流程如下图所示

上述创建的Maven项目也是实现了该注入
运行上述文件,得到的运行结果如下:

现在我们的BookService,引用类型只有一个BookDao,能不能再BookService引用多个类型呢,是可以的,我们在BookService中引入UserDao,遵循上述流程,主要修改下述几块的代码。

运行结果如下:

简单类型:

例子实现:
我们在BookDaoImpl中 添加基本变量 int 和string,实现对应的set方法,然后在配置文件中,对bookDao bean对象作出修改,注意值是value,不是setter注入的ref。

运行后结果如下:

构造器注入
引用类型
我们用刚刚创建的maven项目,重新实现上述的功能。
在BookServiceImpl文件中,构造器注入与setter注入的区别,就是换了一种构造方法,将对象传给类,另外需要修改配置文件,如图所示

和上述一样,再引用一个UserDao类型,更改方式类似,如下图所示:

运行结果如下:

简单类型
标准写法
构造方法类似setter类型的构造方法,大同小异,代码更改方式如下:

运行结果如下:

上述已经完成了配置文件的更改,但是我们发现,配置文件中结构体注入相关的参数,与构造方法中的形参耦合性很强,一但形参改名,配置文件中的参数必须跟着改名,所以有了以下几种解决方法:
1、解决形参名不耦合的问题
干脆不给配置文件中 传递形参名,如何区分不同的形参呢,可以通过类型区分,如下:

2、解决形参类型重复的问题
也不传入类型了,根据形参的位置,直接传入索引

注入方式选择
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现(强制依赖指对象在创建的过程中必须要注入指定的参数)
- 可选依赖使用setter注入进行,灵活性强(可选依赖指对象在创建过程中注入的参数可有可无)
- Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
依赖自动装配
IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配
自动装配方式
● 按类型(常用)
● 按名称
● 按构造方法
● 不启用自动装配
实例:创建一个与上述例子完全相同的例子,这一次只需要在xml文件中 删除掉手动注入,加入autowire参数即可

注意事项
- 需要注入属性的类中对应属性的setter方法不能省略
- 被注入的对象必须要被Spring的IoC容器管理
- 按照类型在Spring的IOC容器中如果找到多个对象,会报
如果有多个bean对象,将autowire改为按名称 autowire = "byType"

最后对于依赖注入,需要注意一些其他的配置特征:
- 自动装配用于引用类型依赖注入,不能对简单类型进行操作
- 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
- 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
- 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
集合注入
实例:创建一个项目,结构如下:

内容如下:

在BookDaoImpl类中初始化集合,给出对应的set方法,然后再xml中进行配置,各个类型的集合配置方式如图所示,这些都是注入的基本数据类型(常用)

如果要注入的是引用对象,要配置bean,且要指定ref,写法如下图(不常用)

运行结果如下:

总结:
● 注入数组类型数据
● 注入List类型数据
● 注入Set类型数据
● 注入Map类型数据
● 注入properties类型数据
说明:
- property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写、、、、标签
- List的底层也是通过数组实现的,所以和标签是可以混用
- 集合中要添加引用类型,只需要把标签改成标签,这种方式用的比较少
到此这篇spring官方教程(springg)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/40226.html