Spring学习笔记(2)——Spring IoC 详解

Spring IoC详解

Spring IoC 概述

IoC:控制反转理念
  • 将原本在程序中手动创建对象的控制权,交由Spring框架来管理
  • 正控:若要使用某个对象,需要自己去负责对象的创建。
  • 反控:若要使用某个对象,只需要从Spring容器中获取需要使用的对象,不关心对象的创建过程。(把创建对象的控制权反转给了Spring框架)
Spring IoC 阐述

控制反转的概念:控制反转是一种通过描述(在Java中可以是XML或者注解)并通过第三方(Spring)去产生或获取特定对象的方式。
好处:降低对象之间的耦合、我们不需要理解一个类的具体实现,只需要直到它有什么用就好了(直接向IoC容器拿)。

Spring IoC 容器

Spring会提供IoC容器来管理和容纳我们所开发的各种各样的Bean,并且我们可以从中获取各种发布在Spring IoC容器里的Bean,并且通过描述可以得到它。

Spring IoC 容器的设计

Spring IoC 容器的设计主要是基于以下两个接口:

  • BeanFactory
  • ApplicationContext
    其中ApplicationContext是BeanFactory的子接口之一,换句话说:BeanFactory 是 Spring IoC 容器所定义的最底层接口,而ApplicationContext是其最高级接口之一,并对BeanFactory功能做了许多的拓展,所以在绝大部分的工作场景下,都会使用ApplicationContext作为Spring IoC容器
    Diagram for ApplicationContext
BeanFactory

从上图可以看到,BeanFactory位于设计的最底层,它提供了Spring IoC最底层的设计,它提供的方法有:
BeanFactory的方法

  • 【getBean】对应了多个方法来获取配置给Spring IoC容器的Bean。
    1. 按照类型获取bean:
      bean = (Bean) factory.getBean(Bean.class);
      要求在Spring中只配置了一个这种类的实例,否则报错。
    2. 按照bean的名字获取bean:
      bean = (Bean) factory.getBean("beanName");
      这种方法不太安全,IDE不会检查其安全性(关联性)
    3. 按照名字和类型拿bean:(推荐)
      bean = (Bean) factory.getBean("beanName", Bean.class);
  • 【isSingleton】用于判断是否单例,如果判断为真,意思是该Bean在容器中是作为一个唯一单例存在的。
  • 【isPrototype】与isSingleton相反,如果判断为真,意味着当你从容器中获取Bean,容器就为你生成一个新的实例。

默认情况下,【isSingleton】为true,而【isPrototype】为false。

  • 【isTypeMatch】一个按Java类型匹配的方式。
  • 【getAliases】获取别名的方法。
    这就是Spring IoC最底层的设计,所有关于Spring IoC的容器将会遵守它所定义的方法。
ApplicationContext

根据ApplicationContext的类继承关系图,可以看到ApplicationContext接口拓展了许许多多的接口,因此它的功能十分强大,在实际应用中很常见。
ClassPathXmlApplicationContext:
是ApplicationContext的一个子类,应用:

  1. 现在src目录下创建一个bean.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 通过 xml 方式装配 bean -->
    <bean name="source" class="pojo.Source">
        <property name="fruit" value="橙子"/>
        <property name="sugar" value="多糖"/>
        <property name="size" value="超大杯"/>
    </bean>
</beans>

这里定义了一个bean,这样Spring IoC容器在初始化的时候就能找到它们,然后使用ClassPathXmlApplicationContext容器就可以将其初始化:(Source是一个javaBean,有三个属性:fruit、sugar、size及其get和set方法)

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Source source = (Source) context.getBean("source", Source.class);

System.out.println(source.getFruit());
System.out.println(source.getSugar());
System.out.println(source.getSize());

这样就会使用Application的实现类ClassPathXmlApplicationContext去初始化Spring IoC容器,然后开发者就可以通过IoC容器来获取资源了。

AppilicationContext 常见实现类
  1. ClassPathXmlApplicationContext:
    读取classpath中的资源:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  1. FileSystemXmlApplicationContext:
    读取指定路径的资源:
ApplicationContext ac = new FileSystemXmlApplicationContext("c:/applicationContext.xml");
  1. XmlWebApplicationContext:
    需要在web的环境下才可以运行:
XmlWebApplicationContext ac = new XmlWebApplicationContext(); // 这时并没有初始化容器
ac.setServletContext(servletContext); // 需要指定ServletContext对象
ac.setConfigLocation("/WEB-INF/applicationContext.xml"); // 指定配置文件路径,开头的斜线表示Web应用的根目录
ac.refresh(); // 初始化容器
BeanFactory 和 ApplicationContext 的区别
  • BeanFactory: 是Spring中最底层的接口,只提供了最简单的IoC功能,负责配置、创建和管理bean。在应用中,一般不使用BeanFactory,而推荐使用ApplicationContext(应用上下文)。
  • ApplicationContext: 继承了BeanFactory,拥有基本的IoC功能,此外,还提供以下功能:
    • 支持国际化
    • 支持消息机制
    • 支持统一的资源加载
    • 支持AOP功能

Spring IoC 容器的初始化和依赖注入

Spring IoC 容器的两大步骤: Bean的定义、Bean的初始化和依赖注入。

  • Bean 的定义分为3步:
    1. Resource 定位
      Spring IoC 容器先根据开发者的配置,进行资源的定位(通过XML或注解)
    2. BeanDefinition 的载入
      将Resource 定位到的信息,保存到Bean定义(BeanDefinition)中,此时并不会创建Bean的实例
    3. BeanDefinition 的注册
      这个过程就是讲BeanDefinition 的信息发布到Spring IoC容器中
      注意:此时仍然没有对应的Bean的实例。
      完成了以上3步,Bean就在Spring IoC容器中被定义了,但还没有被初始化,更没有完成依赖注入。
  • 初始化和依赖注入
    Spring Bean 还有一个配置选项——【lazy-init】,是否延迟初始化Spring Bean。在没有任何配置的情况下,它的默认值为default,实际值为false,即Spring IoC默认会自动初始化Bean。如果将其设置为true,那么只有当我们使用Spring IoC容器的getBean方法获取它的时候,它才会进行Bean的初始化,完成依赖注入。

IoC 是如何实现的

想象如果我们自己来实现这个依赖注入的功能,我们怎么做?

  1. 读取标注或者配置文件,看看依赖的是哪个Java类(JavaBean),拿到类名。
  2. 使用反射的API,基于类名实例化对应的对象实例。
  3. 将对象实例化,通过构造函数或者setter,传递给引用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值