自己动手写一个spring之IOC_1

写在前面

本文看下如何定义IOC部分内容。

源码

1:基础实现

先来定义要通过ioc管理的bean,如下:

java 复制代码
public class AServiceImpl implements AService {
    public void sayHello() {
        System.out.println("a service 1 say hello");
    } 
}

为了实现IOC,我们需要先来定义一个xml文件,来表达bean信息,如下:

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <bean id = "aservice" class = "com.hc.minispring.ioc.one.v1.test.AServiceImpl"></bean>
</beans>

定义对应xml的bean定义类,beandefinition:

java 复制代码
package com.hc.minispring.ioc.one.v1;

import lombok.Data;

/**
 * bean外部定义的内存映射类
 */
@Data
public class BeanDefinition {
    private String id;
    private String className;

    public BeanDefinition(String id, String className) {
        this.id = id;
        this.className = className;
    }
}

接着定义一个类来读取xml信息,并创建bean信息:

java 复制代码
public class ClassPathXmlApplicationContext {
    private List<BeanDefinition> beanDefinitions = new ArrayList<>();
    private Map<String, Object> singletons = new HashMap<>();
    //构造器获取外部配置,解析出Bean的定义,形成内存映像
    public ClassPathXmlApplicationContext(String fileName) {
        this.readXml(fileName);
        this.instanceBeans();
    }
    private void readXml(String fileName) {
        // ... 具体参看源码
    }
    //利用反射创建Bean实例,并存储在singletons中
    private void instanceBeans() {
        for (BeanDefinition beanDefinition : beanDefinitions) {
            // ... 具体参看源码
        } 
    }
    //这是对外的一个方法,让外部程序从容器中获取Bean实例,会逐步演化成核心方法
    public Object getBean(String beanName) {
        return singletons.get(beanName);
    }
}

接着我们来写一个测试类:

java 复制代码
public class Test1 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("v1/beans.xml");
        AService aService = (AService)ctx.getBean("aservice");
        aService.sayHello();
    }

运行:

复制代码
a service 1 say hello

Process finished with exit code 0

2:根据单一职责改造

面向对象设计原则中的单一原则是一个很重要的原则,它不会让一个类的职责过于繁重,从而让类变得复杂,最终让整体的程序变得维护成本和扩展的成本很高,所以我们接下来对ClassPathXmlApplicationContext进行一番改造。首先对于xml这类定义bean定义的信息,我们将其抽象为资源,而数据是核心,所以我们可以定义core包来放这部分内容,定义Resource接口来代表资源:

java 复制代码
/**
 * 基础资源对应的接口,如xml,注解类等
 */
public interface Resource extends Iterator<Object>{

}

接着我们定义beans目录,放bean相关的内容,如beandifinitionreader(读取resource为bean定义),beandefinition(bean定义),beanfactory(bean的工厂),这样通过beandifinitionreader读取resource为beandifinition,然后通过beanfacotry读取beandifinition信息,创建并维护bean信息。最后在定义一个context目录,来作为整合的入口,使用上述的这些独立的功能完成bean信息的维护,定义类ClassPathXmlApplicationContext:

java 复制代码
/**
 * 集大成者的类,暴漏给用户使用
 */
public class ClassPathXmlApplicationContext implements BeanFactory {
    BeanFactory beanFactory;

    public ClassPathXmlApplicationContext(String fileName) {
        Resource res = new ClassPathXmlResource(fileName);
        BeanFactory bf = new SimpleBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
        reader.loadBeanDefinitions(res);
        this.beanFactory = bf;
    }

    @Override
    public Object getBean(String beanName) throws NoSuchBeanDefinitionException {
        return this.beanFactory.getBean(beanName);
    }

    @Override
    public void registerBeanDefinition(BeanDefinition bd) {
        this.beanFactory.registerBeanDefinition(bd);

    }
}

最终如下:

测试:

java 复制代码
public class Test1 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("v2/beans.xml");
        AService aService = (AService)ctx.getBean("aservice");
        aService.sayHello();
    } 
} 

运行:

复制代码
a service 1 say hello v2

Process finished with exit code 0

这样我们就按照单一职责将不同的功能使用不同的类实现,并且将一类功能按照包的方式组织在了一起,大概如下:

复制代码
core包:
    资源相关
beans包:
    bean处理相关
context包:
    用户入口,统筹

写在后面

参考文章列表

01|原始IoC:如何通过BeanFactory实现原始版本的IoC容器?

相关推荐
Tisfy6 小时前
LeetCode 1927.求和游戏:抵消+看最值
java·leetcode·游戏·题解·博弈论
东风破_10 小时前
从输入 juejin.cn 到看到页面:DNS、Nginx、服务器集群与 CDN 到底在做什么?
后端·mysql
东风破_11 小时前
从 0 设计一个博客数据库:用户、头像与文章表应该怎么建?
后端·mysql
大鸡腿同学11 小时前
黄仁勋点透的 AI 真相:能实现你知道但做不到的,却实现不了你不知道的
后端
FfHUCisI11 小时前
Go 编译过程全景
开发语言·后端·golang
FfHUCisI11 小时前
Golang 语法分析与 AST:Parser 与 go/ast
开发语言·后端·golang
秋饼12 小时前
JDK 27 企业级 AI 服务落地实战:G1 默认、紧凑对象头、后量子 TLS 与 JFR 脱敏全解析
java·ai·技术分享·后端开发
卓怡学长12 小时前
w176基于SpringBoot的医院管理系统
java·spring boot·spring·maven·intellij-idea
lemon_sjdk12 小时前
ObjectProperty
java·开发语言·算法
大模型码小白12 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring