Рукописный фреймворк Spring ioc с нуля, углубленное изучение исходного кода Spring

задняя часть Spring

IoC

IocЭто упрощенная версия основных функций Spring ioc, которую легко изучить и понять принцип.

творческая цель

Spring использую давно, причем очень часто, на самом деле я так и не успокоился и не изучил исходный код.

Однако есть проблема с исходным кодом spring, то есть он слишком абстрактный, что приводит к увеличению стоимости обучения.

Поэтому этот проект постепенно углубляется и реализует только основные функции спринга, чтобы и себе, и другим было удобно изучать основные принципы спринга.

сердцевина весны

Ядро Spring — это spring-beans, и все, что стоит за spring-boot и spring-cloud, построено на этом фундаменте.

Когда кто-то спросит вас о Spring, я надеюсь, вы сможете рассказать о своем собственном более глубоком понимании Spring ioc, а не просто об этом в Интернете.

Что такое МОК

Инверсия управления (сокращенно IoC) — это принцип проектирования в объектно-ориентированном программировании, который можно использовать для уменьшения связи между компьютерными кодами.

Наиболее распространенный способ называется внедрение зависимостей (DI).

Посредством инверсии управления при создании объекта внешний объект, управляющий всеми объектами в системе, передает ему ссылку на объект, от которого он зависит.

Можно также сказать, что зависимости внедряются в объекты.

Зачем нужны МОК

IoC — это метод развязки.

Мы знаем, что Java — объектно-ориентированный язык, в Java все является объектом, и наша программа состоит из нескольких объектов.

Когда наш проект будет становиться все больше и больше, и будет все больше и больше сотрудничающих разработчиков, у нас будет все больше и больше классов, а ссылки между классами будут расти в геометрической прогрессии.

mess

Такой проект просто катастрофа, если ввести Ioc framework.

Платформа должна поддерживать жизненный цикл классов и ссылок между классами.

Наша система будет выглядеть так:

manager

На этот раз мы обнаружили, что связь между нашими классами поддерживается инфраструктурой IoC, а классы внедряются в требуемые классы.

То есть пользователь класса отвечает только за использование, а не за обслуживание.

Доверение профессиональных вещей профессиональным фреймворкам значительно снижает сложность разработки.

быстрый старт

импорт maven

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>ioc</artifactId>
    <version>0.1.11</version>
</dependency>

подготовка к тесту

Весь тестовый код смотрите в тестовом модуле.

  • Apple.java
public class Apple {

    public void color() {
        System.out.println("Apple color: red. ");
    }

}
  • apple.json

Подобно конфигурации xml, мы временно используем json для проверки конфигурации.

[
{"name":"apple","className":"com.github.houbb.ioc.test.service.Apple"}
]

выполнить тест

  • контрольная работа
BeanFactory beanFactory = new JsonApplicationContext("apple.json");
Apple apple = (Apple) beanFactory.getBean("apple");
apple.color();
  • бревно
Apple color: red.

Базовый процесс реализации Spring

инструкция

Все в spring-beans вращается вокруг бобов.

BeanFactory отвечает за управление жизненным циклом bean-компонентов.В этом разделе показан простой процесс реализации первого раздела.

Основной процесс Spring

Spring IoC в основном состоит из следующих шагов.

  1. Инициализируйте контейнер IoC.

  2. Прочтите файл конфигурации.

  3. Преобразуйте файл конфигурации в структуру данных, идентифицируемую контейнером (эта структура данных называется BeanDefinition в Spring).

  4. Используйте структуру данных для поочередного создания экземпляров соответствующих объектов.

  5. внедрять зависимости между объектами

Абстракция BeanDefinition

BeanDefinition — это абстракция свойств java bean от spring.После этого уровня абстракции файл конфигурации может быть любым из xml/json/properties/yaml и даже включать пакеты сканирования аннотаций.

Это обеспечивает большую гибкость при расширении пружины.

Учитывая простоту реализации, этот фреймворк изначально реализует только json и сканирование пакетов на основе аннотаций.

Если на более позднем этапе есть время, вы можете рассмотреть возможность добавления реализации xml.На самом деле, это больше рабочей нагрузки по разбору xml, а основной процесс уже полностью реализован.

Реализовать фрагменты исходного кода

BeanDefinition связанные

Содержит базовую информационную абстракцию для java bean-компонентов.

  • BeanDefinition.java

Его реализация по умолчаниюDefaultBeanDefinition.java, который является самым простым java POJO, реализующим интерфейс

видетьDefaultBeanDefinition

/**
 * 对象定义属性
 * @author binbin.hou
 * @since 0.0.1
 */
public interface BeanDefinition {

    /**
     * 名称
     * @return 名称
     * @since 0.0.1
     */
    String getName();

    /**
     * 设置名称
     * @param name 名称
     * @since 0.0.1
     */
    void setName(final String name);

    /**
     * 类名称
     * @return 类名称
     */
    String getClassName();

    /**
     * 设置类名称
     * @param className 类名称
     * @since 0.0.1
     */
    void setClassName(final String className);

}

Управление ядром BeanFactory, связанное с

  • BeanFactory.java
/**
 * bean 工厂接口
 * @author binbin.hou
 * @since 0.0.1
 */
public interface BeanFactory {

    /**
     * 根据名称获取对应的实例信息
     * @param beanName bean 名称
     * @return 对象信息
     * @since 0.0.1
     */
    Object getBean(final String beanName);

    /**
     * 获取指定类型的实现
     * @param beanName 属性名称
     * @param tClass 类型
     * @param <T> 泛型
     * @return 结果
     * @since 0.0.1
     */
    <T> T getBean(final String beanName, final Class<T> tClass);

}
  • DefaultBeanFactory.java

Для самой базовой реализации интерфейса исходный код выглядит следующим образом:

/**
 * bean 工厂接口
 * @author binbin.hou
 * @since 0.0.1
 */
public class DefaultBeanFactory implements BeanFactory {

    /**
     * 对象信息 map
     * @since 0.0.1
     */
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

    /**
     * 对象 map
     * @since 0.0.1
     */
    private Map<String, Object> beanMap = new ConcurrentHashMap<>();

    /**
     * 注册对象定义信息
     * @since 0.0.1
     */
    protected void registerBeanDefinition(final String beanName, final BeanDefinition beanDefinition) {
        // 这里可以添加监听器
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    @Override
    public Object getBean(String beanName) {
        Object bean = beanMap.get(beanName);
        if(ObjectUtil.isNotNull(bean)) {
            // 这里直接返回的是单例,如果用户指定为多例,则每次都需要新建。
            return bean;
        }

        // 获取对应配置信息
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(ObjectUtil.isNull(beanDefinition)) {
            throw new IocRuntimeException(beanName + " not exists in bean define.");
        }

        // 直接根据
        Object newBean = createBean(beanDefinition);
        // 这里可以添加对应的监听器
        beanMap.put(beanName, newBean);
        return newBean;
    }

    /**
     * 根据对象定义信息创建对象
     * @param beanDefinition 对象定义信息
     * @return 创建的对象信息
     * @since 0.0.1
     */
    private Object createBean(final BeanDefinition beanDefinition) {
        String className = beanDefinition.getClassName();
        Class clazz = ClassUtils.getClass(className);
        return ClassUtils.newInstance(clazz);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getBean(String beanName, Class<T> tClass) {
        Object object = getBean(beanName);
        return (T)object;
    }

}

Среди них ClassUtils — класс инструментов отражения на основе классов.ClassUtils.java

JsonApplicationContext

Базовая реализация основана на конфигурационном файле json, см. пример кода в начале использования.

  • JsonApplicationContext.java
/**
 * JSON 应用上下文
 * @author binbin.hou
 * @since 0.0.1
 */
public class JsonApplicationContext extends DefaultBeanFactory {

    /**
     * 文件名称
     * @since 0.0.1
     */
    private final String fileName;

    public JsonApplicationContext(String fileName) {
        this.fileName = fileName;

        // 初始化配置
        this.init();
    }

    /**
     * 初始化配置相关信息
     *
     * <pre>
     *  new TypeReference<List<BeanDefinition>>(){}
     * </pre>
     *
     * 读取文件:https://blog.csdn.net/feeltouch/article/details/83796764
     * @since 0.0.1
     */
    private void init() {
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
        final String jsonConfig = FileUtil.getFileContent(is);
        List<DefaultBeanDefinition> beanDefinitions = JsonBs.deserializeArray(jsonConfig, DefaultBeanDefinition.class);
        if(CollectionUtil.isNotEmpty(beanDefinitions)) {
            for (BeanDefinition beanDefinition : beanDefinitions) {
                super.registerBeanDefinition(beanDefinition.getName(), beanDefinition);
            }
        }
    }

}

резюме

На данный момент базовый Spring ioc в основном реализован.

Если вы хотите продолжить обучение, вы можете обратиться к следующим ветвям кода соответственно.

описание ветки

v0.0.1-BeanFactory базовая реализация

v0.0.2-ListBeanFactory базовая реализация

v0.0.3 - Одиночки и отложенная загрузка

v0.0.4 - методы инициализации и уничтожения

v0.0.5 - Дополнения RespCode и оптимизация кода

v0.0.6 - Конструктор и factoryMethod для создания новых объектов

v0.0.7-свойство настройки свойства

v0.0.8-Aware Listener и PostProcessor

v0.0.9 - Наследование родительского свойства

v0.1.0 - Циклическое обнаружение зависимостей

v0.1.1-@Configuration-конфигурация кода Java

v0.1.2 - определение объекта @Bean-java

v0.1.3-@Lazy-@Scope-конфигурация свойства объекта Java

v0.1.4 - Импорт конфигурации @Import

v0.1.5 - Построение параметров @Bean и @Description

v0.1.6 - поддержка автоматически подключаемых аннотаций @Autowired

v0.1.7 - @Primary указывает аннотацию приоритета

v0.1.8 - Поддержка условной аннотации @Conditional

v0.1.9 - Реализация среды и @Profile

v0.1.10 - Связанный профиль свойства и реализация @Value/@PropertyResource

v0.1.11 - Поддержка сканирования пакетов @ComponentScan

Расширенное чтение

Что такое Java IOC-00-ioc