开发者学堂课程【高校精品课-厦门大学 -JavaEE 平台技术:控制反转】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/80/detail/15902
控制反转
内容介绍:
一、控制反转
二、spring 容器自动装配例子
一、控制反转
1、控制反转是 spring 容器的一个重要特征,控制反转是指在spring容器中间 Bean 对自己的依赖是不需要自己管理的,可以通过配置信息告诉spring之间的依赖是什么,但很多时候 spring 容器是可以基于某一种规则自动的管理spring中间的所有 Bean 对象之间的依赖。Spring 容器怎样负责管理 Bean 对象的依赖?
它采用依赖注入(DI)的方式来实现控制反转,需要通过注解的方式告诉spring容器 Bean 对象之间是会相互关联的,最常用的一个注解是@Autowired,在 Bean 对象的属性或 Bean 对象的方法前面用 Autowired 注解告诉 spring容器这样一个属性,或者在方法里的参数是需要由spring容器来注入对象的。
2、默认匹配规则
Spring容器首先会查询对应的类型是相同的 Bean 对象,如果同一个类型的 Bean 对象只有一个,那他就会把这个 Bean 对象装配给属性或者装配给方法的参数。如果 Autowired 所绑定的数据类型得到的结果不是一个的话,Autowired 会根据变量的名称来查找,也就是我们绑定的属性名称,或方法中间参数的名称,跟 Bean 对象的ID是一样的,就会把它对上来。
二、spring容器自动装配例子
1、通过代码看 Autowired 是怎样使用的?下面是spring容器自动装配的例子,在这个例子中间做了三个让它自动装配的类,分别是 Boss、Car、Office,把 Car 和 Office 装到 Boss 里去,装配的方式可以有多种,可以把它写在属性前面或构造函数前面,也可以写在 setter 方法前面,所以 Boss 做了三个类,分别对应三种不同的把 Bean 对象把它装配上来的方式,而 Car 的对象和 Office 对象做了一些特别的处理,对于 Office 对象来说比较简单,它是一个普通的对象;但是 Car 做了一个接
口,在 Car 底下做了两个实例类,分别是 Toyota 和 Haval。
做着两个实例类的目的是想看一下在自动装配的时候,如果在 Car 里有两个实例的
话,它是怎样来装配的?通过ID来确认最后装配的是哪一个对象?
下面来看一下代码,自动装配例子在第一章的 Spring From Work 里面的autowireddemo 工程下,在这个工程底下建了几个 Bean。第一个非常简单的
Bean 叫 Office,用注解来表现它,这个 Bean 里面没有任何实现。
第二个建了一个接口叫 Car,这个接口前面没有任何注解,
2、有两个对象来实现 Car 的接口,分别是 Toyota 和 Haval,这个 component 里没写任何内容,因为只想看一下它自动绑定的过程,它实现了 Car 的接口。
public
class
Toyota
implements
Car
{
另外一个是Haval,也实现了 Car 的接口。
public class Haval implements Car {
需要把 Car 和 Office 注入到 Boss 里,Boss 写了三个类,分别用来演示三种不同的注入方式,第一个是 Boss_constructor,因为想通过它的构造函数注进来,在这个例子中首先用的是 car 类型。
@Component
public class Boss_constructor{
private car car;
private office office;
@Autowired
public Boss_constructor(Car car
,
Office office){
this.car = car;
this.office = office;
构造函数中间有两个参数,一个是car,一个是office。在这个构造函数中间,如果是ncanr类型的话,在代码中间是会出问题的,因为跑起来的时候 Bean 不知道是要把 Toyota 注入进去,还是把 Haval 注入进去,先跑一下这段代码,看看它的问题在什么地方?跑起来之后发现它会报错,报的错是application where to start 起不来。
起不来的原因是因为partment零的 boss_constructor 第一个参数需要一个 Bean 对象,但是在spring容器中间按照配置信息只能找到两个,分别是 Toyota 和 Haval,这样就没办法把它绑定上去。
3、我们可以把代码运维改一下,不改它的的类型,把变量名称改成 Toyota,这里面所有的 Bean 对象都没有定义 id,所以他的ID是类名的首字母小写,Toyota 类型的 Bean 对象ID是 Toyota,改完之后再 spring-bootrun 跑一下,这个时候就没有
问题了。
其他的也类似,下面看一下通过 property 来注进去的。
@Component
public class boss_property {
@Autowiret
private Car haval:
@Autowire
private office office;
property 不需要写构造函数前,不需要写在方法前面,直接写在属性前面,这样当他实例化出来的时候会根据类型找对应的,这个例子中间 car 注册的不是 Toyota,注册是 Haval,这样跑起来就不会出错。
4、第三个是通过setter函数。
@Component
public class Boss_Setter {
private Car car;
private
O
ffice office;
@Autowired
public void set
C
ar(car toyota){
this.car = toyota;
@
Autowired
public void set
O
ffice(Office office) { this.office = office; }
setter函数是注册 Toyota,虽然它是 car 的类型,但是在 setter 函数的参数上面它的名字叫做 toyota,这样就会用 ID 找 car 类型下的 ID 叫做 Toyota 的 Bean 对象把它注册进来,这是自动装配的一个过程。现在已经没有错了,但是跑起来以后,怎样知道自动装配是否正确?利用了在下一章要讲的 Aprit 接口,通过一个界面的工程叫做 Admits UI,这次只是看它的结果,把界面的工程跑起来,界面的工程在配置文件中定义了端口在8081,因为 autowired 端口放在8080,把 autowired 工程也跑起来,跑在8080。两个工程都跑起来以后,就可以看8081端口上 Spring Boot Admin 工具,这个工具能看到在服务器集群中间到底跑了多少 Spring Boot
的 Application?现在只有一个,
要看的是这个 Bean 对象,利用application接口可以看到 Bean 对象的一些配置,到 wallboard 里看 Application 的配置是什么?
关心的是这里面绑定了多少 Bean ,这里面有内部的 Bean ,也有我们定义的。
首先看到的是 boss_Setter Bean,boss_Setter Bean 绑上的是 Toyota,虽然它 Bean 中间定义的类型是接口类型,但是因为它用ID找到了toyoty对象,constructor 绑上的也是 Toyota,boss_property 绑上的是 Haval,这样就能看到它绑定上去的东西都是不同类型的对象,根据ID找上去的。