Daguai scores! Hand-written Spring ioc framework, fiercely "luting" Spring source code

It is estimated that many friends use spring for a long time, and use spring very frequently. In fact, they have never calmed down and learned about the source code.

Do you feel this way?

But there is a problem with the spring source code, that is, it is too abstract, which leads to higher learning costs. So this article goes from the shallower to the deeper, and only realizes the core functions of spring, which is convenient for yourself and others to learn the core principles of spring.

The article is a bit long, read it patiently! If it helps you, remember Sanlian!

Insert picture description here

The core of spring

The core of Spring is spring-beans, and all subsequent spring-boot and spring-cloud are built on this foundation.
When someone asks you about spring, I hope you can talk about your deeper insights about spring ioc, rather than a few words from the Internet.

In addition, I have compiled and collected interview knowledge points from more than 20 years of companies, as well as various Java core knowledge points for free to share with you. The following are just some screenshots.
If you want information, you can also click directly to enter: Password: csdn , get it for free.

Insert picture description here

What is IOC

Inversion of Control (Inversion of Control, abbreviated as IoC) is a design principle in object-oriented programming that can be used to reduce the coupling between computer codes.
The most common method is called Dependency Injection (DI).
Through inversion of control, when an object is created, an external entity that regulates all objects in the system passes the references of the objects it depends on to it.
It can also be said that the dependency is injected into the object.

Why do I need IOC

IoC is a method of decoupling.
We know that Java is an object-oriented language. Everything is Object in Java. Our program is composed of several objects.
When our projects are getting bigger and more developers working together, our classes will become more and more, and the references between classes will increase exponentially.

Insert picture description here
Such a project is simply a disaster, if we introduce the Ioc framework.

The framework maintains the life cycle of classes and references between classes.

Our system will become like this: At
Insert picture description here
this time we found that the IoC framework is responsible for maintaining the relationship between our classes, and at the same time injecting the classes into the required classes.

That is, the user of the class is only responsible for use, not maintenance.

Delivering professional tasks to a professional framework will greatly reduce the complexity of development.

Quick start

maven introduction

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

Test preparation

For all test codes, see the test module.

  • Apple.java
public class Apple {
    
    

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

}
  • apple.json

Similar to the xml configuration, we temporarily use json for configuration verification.

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

Perform the test.

  • test
BeanFactory beanFactory = new JsonApplicationContext("apple.json");
Apple apple = (Apple) beanFactory.getBean("apple");
apple.color();
  • Log
Apple color: red.

Spring basic implementation process

Description

Spring-beans is all about beans.

BeanFactory is responsible for the related management of the bean life cycle. This section shows the simple implementation process of the first section.

spring core process

Spring IoC mainly includes the following steps.

  1. Initialize the IoC container.

  2. Read the configuration file.

  3. Convert the configuration file into a data structure that the container recognizes (this data structure is called BeanDefinition in Spring)

  4. Use the data structure to instantiate the corresponding objects in turn

  5. Dependencies between injected objects

BeanDefinition abstraction

BeanDefinition is spring's abstraction of java bean properties. After this level of abstraction, the configuration file can be any of xml/json/properties/yaml, and even includes annotation scanning packages.
It brings great flexibility to the expansion of spring.
Taking into account the simplicity of implementation, this framework initially only implements two methods, json and annotation-based scanning packages.
Later, if you have time, you can consider adding the implementation of xml. In fact, it is more of the parsing workload of xml, and the core process has been fully realized.

Implementation source code excerpt

BeanDefinition related

Contains basic information abstraction for java beans.

  • BeanDefinition.java

The default implementation is DefaultBeanDefinition.java, which is the most basic java POJO for interface implementation

/**
 * 对象定义属性
 * @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 core management related

  • 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

The most basic implementation of the interface, the source code is as follows:

/**
 * 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;
    }

}

Among them, ClassUtils is a reflection tool class based on class

JsonApplicationContext

The basic implementation based on the json configuration file, see the example code at the beginning for the usage method.

  • 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);
            }
        }
    }

}

summary

So far, a most basic spring ioc is basically realized.

The sea of ​​learning is endless, let's work hard together!

Ps: Those in need can click to enter directly: Password: csdn , get it for free.

Interview topic documents.

Insert picture description here

Technical documents

Insert picture description here

Real big factory experience

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_41770757/article/details/109344610