代码改变世界

Spring Framework源代码解析之IOC容器(一)

  飘扬的红领巾  阅读(2791)  评论(0编辑  收藏  举报

    最近开始写博客,觉得这样对自己很有好处,可以从头到尾把散乱的知识梳理一遍,通过自己的理解把它写下了,这个过程受益匪浅。今天写Spring的随笔,使用Spring大概有3年时间,可大多时候只是使用它的特性,并没有深入学习它。Spring的源码据网友说写的很漂亮,我也来学习一下。

IOC之HelloWorld

    假设我们有这样一个业务,根据产品的ID,从产品库中取得该产品的详细信息。用户接口可能是Web浏览器、桌面软件或者超市的条形码扫描器,总之会用一个类来接受用户请求,我们暂且定名为ProductAction.java.

而具体处理逻辑则是放在产品服务接口中,ProductService.java。该接口有一个实现类ProductServiceImpl.java,具体实现写在ProductServiceImpl.java中。代码如下:

ProductService.java

1
2
3
4
5
6
7
8
9
10
11
public interface ProductService {
    /**
     * @Title: getProduct
     * @Description: 根据ID获取产品信息
     * @param id
     * @return Product
     *
     * @throws
     */
    Product getProduct(String id);
}

ProductServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service("productService")
public class ProductServiceImpl implements ProductService {
 
    /* (non-Javadoc)
     * @see com.cnblogs.leefreeman.domain.service.ProductService#getProduct(java.lang.String)
     */
    @Override
    public Product getProduct(String id) {
        // TODO 此处编写取得产品详细信息的逻辑
        return null;
    }
 
}

Product.java

ProductAction. java

1
2
3
4
5
6
7
8
9
10
11
12
public class ProductAction {
    /**
     * 注入ProductServiceImpl.java
     */
    @Resource(name = "productService")
    private ProductService productService;
 
    public Product getProductById(String id) {
        Product product = productService.getProduct(id);
        return product;
    }
}

Spring配置文件

这样就可以实现往ProductAction类中注入指定的ProductService,而具体业务的交给了ProductServiceImpl处理。

何为IOC?

    从上例可以看出,通过Spring的IOC特性,将ProductService具体的实现类注入到ProductAction中,从而ProductAction可以调用ProductService的方法进行逻辑处理。在没有使用Spring的情况下,要完成以上功能,也可以通过new关键字,将ProductSerivce接口的实现类实例化出来。但他们的区别在哪里呢?当使用new关键字实例化对象时,ProductAction类对ProductService实现类的实例化具有控制权;而使用Spring IOC时,ProductAction和ProductService之间的关系则通过Spring来配置(通过注解或者XML配置文件),而对ProductService的控制权由ProductAction转移到了Spring IOC容器上,这就是所谓的控制反转。IOC特性的直接用处就是解耦,在ProductAction中,我们并没有看到对ProductService实现类的依赖,而它们之间的依赖关系则是通过第三方(Spring IOC)来维护。

IOC工作流程

Step1:系统运行时,Spring开始启动,指定将加载的配置文件。

应用程序:

1
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");

Web应用:

web.xml

1
2
3
4
5
6
7
<context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:spring-hibernate-mysql.xml</param-value>
    </context-param>
    <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

Step2:接着AbstractApplicationContext类开始调用prepareRefresh方法,对ApplicationContext进行刷新。

Step3:XmlBeanDefinitionReader类调用loadBeanDefinitions方法进行配置文件加载,配置文件中定义的Java Bean会被加载在IOC容器的一个HashMap当中。HashMap的key就是Bean的id,HasMap的value就是这个Java Bean。(当中详细过程分为定位、载入、注册,我们后面再详细说明)

Step4:依赖注入,当用户向IOC容器索要Bean时,将触发BeanFactory中的getBean方法,当然不同类型的配置会调用不同的BeanFactory,如XmlBeanFactory。从而得到相应的JavaBean。

小结

    上面简要介绍了Spring IOC的特性,对IOC的理解,IOC容器的大致工作流程,下文将依据上述流程详细解析IOC容器的实现。

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示