IOC思想

IOC:控制反转

IOC是Spring的核心,贯穿始终

对于Spring框架来说,就是由spring IOC容器来负责控制对象的生命周期和对象间的关系

1.在传统开发模式下,我们是采用直接new一个对象的方式来创建对象,也就是所依赖的对象由自己控制

但是这种可以交给IOC容器来控制对象

2.控制的是对象

3.有了IOC之后,所依赖的对象直接由Ioc容器创建后注入到被注入的对象中,依赖的对象由原来的主动获取变为被动接受,故称之为反转

4.所依赖的对象的获取  被反转

Spring所倡导的开发方式:即所有的类都会在spring容器中登记,告诉spring 你是什么对象,你需要什么对象

之后spring会在系统运行到适当的时候,把你要的对象给你,同时也把你交给其他需要你这个对象的对象。所有类的创建和销毁都是由spring来控制的,也就是说控制对象生存周期的不再是引用它的对象,而是spring。

对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转

IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现。比如对象A需要操作数据库,之前我们总是要在A中自己编写代码来获得Connection对象,自从有了spring之后,就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A对象不需要知道。在系统运行中,spring会在适当的时候制造一个Connection,就像打针一样,将其注射到A中,这样就完成了对各个对象之间关系的控制。A需要依赖Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的

Spring的IOC容器在实现控制反转和依赖注入的过程中,可以划分为两个阶段

1.容器启动阶段

2.Bean实例化阶段

Spring的IoC容器在实现控制反转和依赖注入功能的时候不是一蹴而就的,也分了两个阶段,并且大致对两个阶段所做的事情有一个印象

容器启动阶段的讲解

1.IOC的技术实现方式

“伙计,来杯啤酒!”当你来到酒吧,想要喝杯啤酒的时候,通常会直接招呼服务生,让他为你送来一杯清凉解渴的啤酒。同样地,作为被注入对象,要想让IoC容器为其提供服务,并将所需要的被依赖对象送过来,也需要通过某种方式通知对方。

  • 如果你是酒吧的常客,或许你刚坐好,服务生已经将你最常喝的啤酒放到了你面前如果你是初次或偶尔光顾
  • 也许你坐下之后还要招呼服务生,“Waiter,Tsingdao, please.”
  • 还有一种可能,你根本就不知道哪个牌子是哪个牌子,这时,你只能打手势或干脆画出商标图来告诉服务生你到底想要什么了吧!

不管怎样,你终究会找到一种方式来向服务生表达你的需求,以便他为你提供适当的服务。那么,在IoC模式中,被注入对象又是通过哪些方式来通知IoC容器为其提供适当服务的呢?

常用的有两种方式:构造方法注入和setter方法注入,还有一种已经退出历史舞台的接口注入方式,下面就比较一下三种注入方式:

  • 接口注入。从注入方式的使用上来说,接口注入是现在不甚提倡的一种方式,基本处于“退役状态”。因为它强制被注入对象实现不必要的接口,带有侵入性。而构造方法注入和setter方法注入则不需要如此。
  • 构造方法注入。这种注入方式的优点就是,对象在构造完成之后,即已进入就绪状态,可以马上使用。缺点就是,当依赖对象比较多的时候,构造方法的参数列表会比较长。而通过反射构造对象的时候,对相同类型的参数的处理会比较困难,维护和使用上也比较麻烦。而且在Java中,构造方法无法被继承,无法设置默认值。对于非必须的依赖处理,可能需要引入多个构造方法,而参数数量的变动可能造成维护上的不便。
  • setter方法注入。因为方法可以命名,所以setter方法注入在描述性上要比构造方法注入好一些。 另外,setter方法可以被继承,允许设置默认值,而且有良好的IDE支持。缺点当然就是对象无法在构造完成后马上进入就绪状态。其实,这些操作都是由IoC容器来做的,我们所要做的,就是调用IoC容器来获得对象而已

IOC容器为被注入对象提供被依赖对象的方式有:构造方法注入,setter注入,接口注入

构造器注入

构造器注入,顾名思义就是被注入的对象通过在其构造方法中声明依赖对象的参数列表,让外部知道它需要哪些依赖对象。

YoungMan(BeautifulGirl beautifulGirl){
        this.beautifulGirl = beautifulGirl;
}

构造器注入方式比较直观,对象构造完毕后就可以直接使用,这就好比你出生你家里就给你指定了你媳妇

setter 方法注入

对于 JavaBean 对象而言,我们一般都是通过 getter 和 setter 方法来访问和设置对象的属性。所以,当前对象只需要为其所依赖的对象提供相对应的 setter 方法,就可以通过该方法将相应的依赖对象设置到被注入对象中。如下:

public class YoungMan {
    private BeautifulGirl beautifulGirl;

    public void setBeautifulGirl(BeautifulGirl beautifulGirl) {
        this.beautifulGirl = beautifulGirl;
    }
}

相比于构造器注入,setter 方式注入会显得比较宽松灵活些,它可以在任何时候进行注入(当然是在使用依赖对象之前),这就好比你可以先把自己想要的妹子想好了,然后再跟婚介公司打招呼,你可以要林志玲款式的,赵丽颖款式的,甚至凤姐哪款的,随意性较强。

接口方式注入

接口方式注入显得比较霸道,因为它需要被依赖的对象实现不必要的接口,带有侵入性。一般都不推荐这种方式

 

2.IoC容器及IoC容器如何获取对象间的依赖关系

Spring中提供了两种IOC容器

  • BeanFactory
  • ApplicationContext

ApplicationContext是BeanFactory的子类,所以,ApplicationContext可以看做更强大的BeanFactory,他们两个之间的区别如下

  • BeanFactory,基础类型IOC容器,提供完整的IOC服务支持。如果没有特殊指定,默认采用延迟初始化策略(lazy-load)。只有当客户端对象要访问容器中某个收官对象的时候,才对该收官对象进行初始化以及依赖注入操作。所以相对来说,容器启动初期速度较快,所需要的资源有限,并且功能要求不是很严格的场景,BeanFactory是比较合适的IOC容器
  • ApplicationContext。ApplicationContext在BeanFactory的基础上创建,是相对比较高级的容器实现,除了拥有BeanFactoy的所有支持,ApplicationContext还提供了其他高级特性,比如事件发布,国际化信息支持等,Applicationontext所管理的对象,在该容器启动成功之后,默认全部初始化并绑定完成。所以,相对于BeanFactory,ApplicationContext要求更多的资源,同时,因为在启动时就完成所有初始化,容器启动时间也会较长一些。在那些系统资源充足,并要求更多功能的场合中,ApplicationContext类型的容器是比较合适的选择

无论使用哪种容器,都需要以某种方法告诉容器关于对象依赖的信息。只有这样容器才能合理的创造出对象,否则spring也不知道哪个对象依赖哪个对象,如果胡乱注入,那不是创造出了四不像。使用spring提供的方法

  • 通过最基本的文本文件来记录被注入对象和其依赖对象之间的对应关系
  • 通过描述性较强的XML文件格式来记录对应信息
  • 通过编写代码的方式来注册这些对应的信息
  • 通过注解的方式来注册这些对应的信息

 

 

<think>好的,我现在需要回答用户关于Spring Boot是否包含IoC思想以及其实现原理的问题。首先,我得确认用户的基本需求,他们可能已经知道Spring框架的IoC,但想了解Spring Boot在这方面的继承和具体实现。 根据提供的引用内容,引用[1]提到Spring的IoC实现原理,特别是依赖注入(DI)作为IoC的一种实现方式。引用[2]则指出Spring Boot成功的原因之一是对IoC和AOP的应用,所以可以确定Spring Boot确实包含IoC思想。引用[3]展示了传统的XML配置Bean的方式,这可能与Spring Boot的自动配置形成对比。 接下来,我需要组织回答结构。首先明确回答Spring Boot确实包含IoC,然后解释其实现原理,包括自动配置、组件扫描和条件化配置。需要对比传统Spring和Spring Boot的不同之处,比如减少配置的工作量。同时,要结合用户提到的实现原理,可能涉及ApplicationContext、Bean定义等概念。 还要注意用户可能对底层机制感兴趣,比如自动配置是如何实现的,可能涉及@SpringBootApplication注解的组合功能,如@EnableAutoConfiguration、@ComponentScan。需要解释这些注解的作用,以及Spring Boot如何利用spring.factories文件进行自动配置类的加载。 另外,用户可能想知道Spring Boot如何管理Bean的生命周期,这可以联系到ApplicationContext的作用,比如创建、装配、管理Bean。同时,条件化配置如@ConditionalOnClass等注解的使用,说明Spring Boot如何根据环境动态决定Bean的创建,这可以展示其智能化的配置机制。 需要确保回答中提到的技术点都有依据,比如引用中的内容。例如,引用[2]提到Spring Boot成功归功于IoC和AOP,所以在回答中要突出这一点。同时,可能引用[3]中的XML配置例子来对比Spring Boot的自动配置,说明简化配置的过程。 在生成相关问题部分,需要考虑用户可能的后续疑问,比如自动配置原理、如何自定义Bean、与Spring框架的IoC区别等。这些问题需要自然延伸当前回答的内容,帮助用户深入理解。 最后,检查是否符合系统级指令:使用中文,数学公式正确(虽然这里可能用不上),引用标识正确添加。确保回答结构清晰,分点说明实现原理,代码示例正确展示注解和配置类,并且相关问题具有针对性。</think>Spring Boot不仅完全继承了Spring框架的IoC思想,还通过自动化配置机制将其实现推向新高度。以下是具体实现原理分析: ### 一、Spring Boot IoC实现原理 1. **自动配置引擎** 通过`@SpringBootApplication`注解组合实现: ```java @SpringBootConfiguration @EnableAutoConfiguration // 激活自动配置 @ComponentScan // 组件扫描 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 自动配置类通过`META-INF/spring.factories`文件注册,例如: ``` org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration ``` 2. **条件化装配机制** 使用`@Conditional`系列注解实现智能决策: - `@ConditionalOnClass`:类路径存在指定类时生效 - `@ConditionalOnMissingBean`:容器不存在指定Bean时生效 - `@ConditionalOnProperty`:配置参数满足条件时生效 3. **组件扫描增强** 在传统Spring的`@ComponentScan`基础上,通过自动路径推导实现零配置扫描: ``` com.example.application └── Application.java // 主类所在包自动成为扫描根路径 ``` ### 二、与传统Spring的对比 | 特性 | Spring Framework | Spring Boot | |---------------------|------------------------|--------------------------| | 配置方式 | XML/JavaConfig显式声明 | 约定优于配置 | | Bean发现机制 | 手动定义 | 自动扫描+条件装配 | | 依赖管理 | 手动指定版本 | starter POM统一管理 | | 典型配置量 | 50+行基础配置 | 0行基础配置 | ### 三、核心运行流程 1. 创建`ApplicationContext`容器(默认使用`AnnotationConfigServletWebServerApplicationContext`) 2. 加载所有`@Configuration`配置类 3. 执行自动配置: - 解析`spring-autoconfigure-metadata.properties`元数据 - 过滤符合条件的`AutoConfiguration`类 4. 实例化并装配所有Bean(通过构造器注入或字段注入) 5. 执行`CommandLineRunner`等生命周期回调 [^1]: Spring Boot的自动配置机制实质上是IoC容器的高级应用,通过条件判断动态注册Bean定义 [^2]: 启动类中`SpringApplication.run()`方法触发整个IoC容器初始化流程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值