手写一个简单版的Spring

1. 创建一个工程及初始化

  1. 创建Java工程
    手写一个简单版的Spring_第1张图片

  2. 创建对应的包
    手写一个简单版的Spring_第2张图片
    config:为配置类包
    service:定义的将要被自己写的Spring容器管理的组件bean
    spring:里面定义自己写的Spring的类文件,包含子包anno注解包
    test:定义测试类

2. 模仿我们写Spring程序时创建测试类

package com.cjp.test;

import com.cjp.config.AppConfig;
import com.cjp.service.UserInterface;
import com.cjp.spring.ApplicationContext;

import java.lang.reflect.InvocationTargetException;

/**
 * @author 曹见朋
 * @create 2023-11-23-9:30
 */
public class MySpringTest {

    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {

        ApplicationContext applicationContext = new ApplicationContext(AppConfig.class);

        UserInterface UserInterface = (UserInterface) applicationContext.getBean("userService");

        System.out.println("获取到的bean:  " + UserInterface);

        UserInterface.test();

    }
}

在这里,ApplicationContext就是我们将要手写的Spring上下文类,这里是模仿传入一个配置类参数,即全注解开发。

3. 开始实现ApplicationContext

  1. ApplicationContext内容
package com.cjp.spring;

import com.cjp.config.AppConfig;
import com.cjp.spring.anno.Autowired;
import com.cjp.spring.anno.Component;
import com.cjp.spring.anno.ComponentScan;
import com.cjp.spring.anno.Scope;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 曹见朋
 * @create 2023-11-23-9:24
 */


public class ApplicationContext {

    private Class appConfigClass;

    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionConcurrentHashMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<String, Object> singletonBeanConcurrentHashMap = new ConcurrentHashMap<>();
    private ArrayList<BeanPostProcessor> beanPostProcessorArrayList = new ArrayList<>();

    public ApplicationContext(Class<AppConfig> appConfigClass) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        this.appConfigClass = appConfigClass;

        scan(appConfigClass);

        // 把单例bean放入单例bean容器
        for (String beanName : beanDefinitionConcurrentHashMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitionConcurrentHashMap.get(beanName);
            if (beanDefinition.getScope().equals("singleton")) {
                //单例的
                Object bean = createBean(beanName, beanDefinition);
                singletonBeanConcurrentHashMap.put(beanName, bean);
            }
        }


    }

    private void scan(Class<AppConfig> appConfigClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

        ComponentScan componentScanAnnotation = appConfigClass.getAnnotation(ComponentScan.class);

        String classPath = componentScanAnnotation.value();

        String classPath_file = classPath.replace(".", "/");

        ClassLoader classLoader = ApplicationContext.class.getClassLoader();

        URL resource = classLoader.getResource(classPath_file);

        File file = new File(resource.getFile());

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File file1 : files) {
                String file_name = file1.getName();
                String class_path_file = classPath + "." + file_name.substring(0, file_name.length() - 6);
                // System.out.println(class_path_file);  //此时获取的是全限定类名:com.cjp.serviceCartService
                Class<?> aClass = Class.forName(class_path_file);
                if (aClass.isAnnotationPresent(Component.class)) {
                    if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
                        Object instance = aClass.newInstance();
                        beanPostProcessorArrayList.add((BeanPostProcessor) instance);
                    }
                    String bean_name = aClass.getAnnotation(Component.class).value();
                    if (bean_name.equals("") || bean_name == null) {
                        bean_name = Introspector.decapitalize(aClass.getSimpleName());
                        // System.out.println("默认的bean的名字:"+bean_name);
                    }

                    // System.out.println("应当加载该Bean    "+class_path_file);
                    // 先定义BeanDefinition
                    BeanDefinition beanDefinition = new BeanDefinition();
                    beanDefinition.setType(aClass);
                    // 没有scope注解,默认的单例的
                    if (aClass.isAnnotationPresent(Scope.class)) {
                        // 有scope注解,判断scope注解的值,如果为single,则为单例,否则为prototype是多例
                        String scope_value = aClass.getAnnotation(Scope.class).value();
                        if (scope_value.equals("singleton")) {
                            beanDefinition.setScope("singleton");
                        } else {
                            beanDefinition.setScope("prototype");
                        }
                    } else {
                        beanDefinition.setScope("singleton");
                    }
                    // System.out.println(beanDefinition);
                    beanDefinitionConcurrentHashMap.put(bean_name, beanDefinition);
                }

            }
        }

    }

    // 此方法体现了bean的生命周期
    private Object createBean(String beanName, BeanDefinition beanDefinition) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        Class type = beanDefinition.getType();

        Object instance = type.getConstructor().newInstance();

        // 实现依赖注入
        for (Field field : type.getDeclaredFields()) {
            System.out.println(field);
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                Class<?> field_type = field.getType();
                String simpleName = field_type.getSimpleName();
                String capitalize = Introspector.decapitalize(simpleName);  //bean的名字
                Object bean = getBean(capitalize);
                if (bean != null) {
                    field.set(instance, bean);
                } else {
                    throw new RuntimeException("依赖注入错误,未找到" + field_type);
                }
            }
        }
        // Aware
        if (instance instanceof BeanNameAware) {
            ((BeanNameAware) instance).setBeanName(beanName);
        }
        // 初始化前的前置处理器
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorArrayList) {
            instance = beanPostProcessor.postProcessBeforeInitialization(beanName, instance);
        }
        // 初始化
        if (instance instanceof InitializingBean) {
            ((InitializingBean) instance).initialBean();

        }
        // 初始化后的后置处理器
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorArrayList) {
            instance = beanPostProcessor.postProcessAfterInitialization(beanName, instance);
        }
        // 初始化后 AOP  BeanPostProcessor Bean后置处理器

        return instance;
    }

    public Object getBean(String beanName) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        BeanDefinition beanDefinition = beanDefinitionConcurrentHashMap.get(beanName);
        if (beanDefinition == null) {
            throw new NullPointerException();
        } else {
            String scope = beanDefinition.getScope();
            //单例
            if (scope.equals("singleton")) {
                Object bean = singletonBeanConcurrentHashMap.get(beanName);
                if (bean == null) {
                    Object new_bean = createBean(beanName, beanDefinition);
                    singletonBeanConcurrentHashMap.put(beanName, new_bean);
                    return new_bean;
                }
                return bean;
            } else { // 多例
                return createBean(beanName, beanDefinition);
            }
        }
    }
}

  1. 注解类
    手写一个简单版的Spring_第3张图片
package com.cjp.spring.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 曹见朋
 * @create 2023-11-23-9:25
 */

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {

    String value();

}
package com.cjp.spring.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 曹见朋
 * @create 2023-11-23-9:25
 */

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {

    String value() default "";
}

package com.cjp.spring.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 曹见朋
 * @create 2023-11-23-9:25
 */

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {

    String value() default "";
}

package com.cjp.spring.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 曹见朋
 * @create 2023-11-23-9:52
 */

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {

    String value() default "singleton";
}

  1. 回调接口
    在这里插入图片描述
package com.cjp.spring;

/**
 * @author 曹见朋
 * @create 2023-11-23-11:24
 */
public interface BeanNameAware {

    void setBeanName(String beanName);

}

package com.cjp.spring;

/**
 * @author 曹见朋
 * @create 2023-11-23-11:34
 */
public interface BeanPostProcessor {

    Object postProcessBeforeInitialization(String beanName, Object bean);

    Object postProcessAfterInitialization(String beanName, Object bean);
}

package com.cjp.spring;

/**
 * @author 曹见朋
 * @create 2023-11-23-11:29
 */
public interface InitializingBean {

    public void initialBean();


}

  1. 组件类
    手写一个简单版的Spring_第4张图片
  2. 配置类
package com.cjp.config;

import com.cjp.spring.anno.ComponentScan;

/**
 * @author 曹见朋
 * @create 2023-11-23-9:25
 */

@ComponentScan("com.cjp.service")
public class AppConfig {

}

4. 运行效果

手写一个简单版的Spring_第5张图片

你可能感兴趣的:(spring,java,后端)