控制反转IOC

 

 


 

 在person和cleanAir这两个类中,person类依赖于cleanAir类。以往来说,我们是在person类里亲自去new一个cleanAir类的对象,

而这里,Person类不必自己去new,他只需要被动地接收cleanAir对象。这种被动接收依赖对象的依赖方式叫依赖注入。由主动new到被动接收的过程叫做控制反转。

但是这样设计类也有不足的地方。

假如这个类依赖的不再是cleanAir而是dirtyAir,那么就要再增加一个dirtyAir类,还要修改person类的代码。这种强依赖有很大的弊端,一处的变化引起其他地方的变化,而且改变的只是IAir,但是Person也要一起变。为了减少修改的地方,面向接口编程出现了

 

 这里定义了一个接口IAir,cleanAir和dirtyAir实现了IAir。Person类不再直接依赖CleanAir类,而是依赖IAir接口。这样当Person需要依赖dirtyAir对象时,无需修改代码,只要给他修改注入的对象。这个注入的过程,利用Spring框架只需要改一下配置即可实现。

IOC底层实现:

xml解析 工厂模式 反射

工厂模式:

 

 

 

 

IOC接口:

IOC思想基于IOC容器完成,IOC容器的底层是对象工厂

Spring提供IOC容器实现的两种方式:
(1)BeanFactory:IOC容器基本实现,是Spring内部实现的一个接口,不提供给(不建议)开放人员进行使用
(2)ApplicationContext:BeanFactory接口的子接口。提供了更多更强大的功能,一般是面向开放人员进行使用的。
IOC接口这个概念貌似只有尚硅谷提到了,是否有这个概念还有待商榷。

 

选中一个类按CTRL+H可以查看他的类结构

IOC容器--bean管理--xml方式  (这个方式太麻烦了,但是注解方式应该也是基于xml方式实现的,同样的原理,更简单的表达方式。为了更好地学习注解方式,也应当要学一下xml方式)

IOC容器--bean管理--注解方式

注解的基本格式:

@注解名称(属性名称=属性值,属性名称=属性值..)

注解可以作用在类,方法,属性上面。

 创建bean对象:

在类上使用@Component @Service @Repository @Controller 可以创建bean对象。

其作用相当于在xml中配置:

<bean id="" class="com.company"></bean>

如果不添加属性的话,注解生成的bean对象,其id就是类名称首字母小写形式。

也可以@Component(value="")来指定id

这四个注解的功能都是一样的,只是语境不同,@Service用于Service层 ,@Repository用于dao层 ,@Controller用于Controller层,@Component应该是用于pojo层

使用注解是要开启组件扫描的,可以通过xml实现,也可以通过注解实现,个人喜欢完全注解开发,不希望有xml文件

完全注解开发:

创建一个配置类,在其上添加注解@Configuration以标识它是个注解类,

添加注解@ComponentScan(basePackages = {"com.company"}),以开启组件扫描,并指定扫描路径

关于@ComponentScan,要去了解他的属性,通过设置不同的属性,可以实现不同的扫描效果。

@Configuration
@ComponentScan(basePackages = {"com.company"})
public class Config {
}

使用注解注入属性

将依赖对象创建为bean对象后,我们是要去使用他的,所以下一步要进行依赖注入

注解关键字:

@Autowired:根据类型注入,但是,当一个接口有多个实现类时,就无法判断要注入哪一个实现类,所以要再使用@Qualifier以确定是哪一个实现类

@Qualifier:根据名称注入(即id,未设置情况下为类名称首字母小写形式),要与@Autowired一起使用

@Resource:可根据类型注入,也可根据名称注入

@Value:可以给普通类型(非对象类型)注入属性

以上注解在声明的类变量上面添加

每个注解的属性关键字是不同的,每次用就上百度查是不方便的,如何知道所用注解是如何定义的呢?

ctrl+鼠标点击即可实现

使用@Bean进行对象注册

Indicates that a method produces a bean to be managed by the Spring container.

@Bean注解是专用于方法上面的,如果一个方法返回了一个对象,并且在方法之上使用了@Bean,那么这个对象就被spring容器管理了

如果要使用这个对象,有三种依赖注入的方式

1.基于属性的依赖注入

@Component
public class FieldBasedInjection {
    @Autowired
    private InjectedBean injectedBean;
}

2.基于构造函数的依赖注入

@Component
public class ConstructorBasedInjection {

    private final InjectedBean injectedBean;

    @Autowired
    public ConstructorBasedInjection(InjectedBean injectedBean) {
        this.injectedBean = injectedBean;
    }
}

3.基于Setter的依赖注入

@Component
public class SetterBasedInjection {

    private InjectedBean injectedBean;

    @Autowired
    public void setInjectedBean(InjectedBean injectedBean) {
        this.injectedBean = injectedBean;
    }

}

spring目前不推荐使用基于属性的依赖注入,但不影响使用

 

 什么情况下使用@Bean去注册bean对象而不是@Component之类的?

我认为,是在使用别人提供的类的时候,自己创建一个类的时候,我们可以自己在类上面加注解,但是别人的类,我们无法去修改,所以只能通过在返回对象的方法上面,加一个@Bean注解。

根据对IOC的理解,改下如下代码

 

 用这种方法的话,必须的知道这个类的工厂代理类是什么,如果是我,我希望他们能够统一命名xxxFactory

这里创建对象的方法是静态方法,直接使用类去调用。

 

创建RestTemplate的类叫做RestTemplateBuider 创建的方法不是静态方法,需要由对象来创建

 


 

如何查看spring容器里现有的bean有哪些

1.在项目中引入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

在application.properties配置文件里加上

management.endpoints.web.exposure.include=*

 

2.请求localhost:8080/actuator/beans,得到结果

3.复制结果到json格式化网站

 

 

 就可以很直观地看到有没有你想看的bean了。

问题来了,为什么会有这么多不是我亲手注册的bean呢?

 

 

 这里说,通过创建Application类可以定义一些关键bean


使用小技巧

 

 可以导航到所使用的的依赖注册成bean的地方

 

 可以定位到使用了这个bean对象的地方

 

posted @ 2021-08-04 22:30  北征愚人  阅读(110)  评论(0编辑  收藏  举报