就是个复述吧,去年九月份我确实找到工作了,今年5月底离职了,公司技术架构和项目太杂太老

发布时间 2023-07-12 23:12:27作者: gfjf

手写简易spring

`package com.spring.utils;

import com.spring.BeanDefinition;
import com.spring.inteface.Autowried;
import com.spring.inteface.Component;
import com.spring.inteface.ComponentScan;
import com.spring.inteface.Scope;
import com.spring.service.UserService;
import com.sun.security.jgss.GSSUtil;

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.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class ApplicationContext {
private Class aClass; //存储 类类型
private Map<String,BeanDefinition> beanDefinitionMap = new HashMap<>();
private Map<String,Object> singletonDefinitions = new HashMap<>(); //单例池

public ApplicationContext(Class aClass){
    this.aClass = aClass;

    // 扫描bean
    scan(aClass);
    // 扫描完了该创建bean spring也是如此在构造器一开始就创建bean
    // 判断是否是单例的
    for (Map.Entry<String, BeanDefinition> beanDefinitionSet : beanDefinitionMap.entrySet()) {
        String beanName = beanDefinitionSet.getKey();
        BeanDefinition beanDefinition = beanDefinitionSet.getValue(); //beanDefinition
        if (beanDefinition.getScope().equals("singleton")){
            Object bean = createBean(beanName, beanDefinition);
            singletonDefinitions.put(beanName,bean); //存到单例池中
        }
    }
}

private Object createBean(String beanName,BeanDefinition beanDefinition){
    // 这里简单只要用反射就行
    Class aClass1 = beanDefinition.getaClassType();
    Object o = null;
    try {
        o = aClass1.getConstructor().newInstance();
        // 2.1 处理依赖注入的问题 寻找字段中是否有AutoWried注解
        for (Field declaredField : aClass1.getDeclaredFields()) {
            // 判断是否有Autowired注解
            if (declaredField.isAnnotationPresent(Autowried.class)) {
                // 这里注入的是orderWried类型简单点就根据字段名字获取,默认注解注入是单例的
                declaredField.setAccessible(true);
                declaredField.set(o,getBean(declaredField.getName()));
            }

        }
    } catch (InstantiationException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
    } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
    }
    return o;
}
public void scan(Class aClass){
    // 1. 第一步判断传入的类是否有ComponentScan注解
    if (aClass.isAnnotationPresent(ComponentScan.class)){
        //1.2 实现了抽取出注解value值
        ComponentScan componentScan = (ComponentScan) aClass.getAnnotation(ComponentScan.class);
        String path = componentScan.value();  // com.spring.service
        //1.3 注意这里 只是取到扫描的包,需要编译后在本机的的具体位置给classload加载 以保证真是本机地址读取包下的calss类
        String replacePath = path.replace(".", "/"); //com/spring/service
        //1.4 通过类加载器加载这个地址在本机的位置
        ClassLoader classLoader = aClass.getClassLoader();
        URL resource = classLoader.getResource(replacePath); //本机地址 file:/E:/code/spring/target/classes/com/spring/service
        //1.5 分装成file
        String file = resource.getFile();
        File files = new File(file);
        //1.5.1 判断files 是一个文件夹
        if (files.isDirectory()){
            // 1.5.2 遍历得到目录下的文件
            File[] files1 = files.listFiles();
            for (File file1 : files1) {
                //1.5.3 取到每个文件的绝对路径
                String absolutePath = file1.getAbsolutePath(); //E:\code\spring\target\classes\com\spring\service\UserService.class
                absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                absolutePath = absolutePath.replace("\\", ".");
                //1.5.4 判断这个类是否加了Component注解有注解才进行下一步,所以就需要类加载器加载class文件变成类
                try {
                    Class<?> loadedClass = classLoader.loadClass(absolutePath);
                    // 1.5.5 使用beanDefinition判断是否实现
                    if (loadedClass.isAnnotationPresent(Component.class)) {
                        Component annotation = loadedClass.getAnnotation(Component.class);
                        String beanName = annotation.value();// 拿到Component的bean的名称
                        if ("".equals(beanName)) {
                            // 自动生成首字母小写
                            beanName = Introspector.decapitalize(loadedClass.getSimpleName());
                        }
                        // Bean 需要封装起来
                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setaClassType(loadedClass);

                        //1.5.6 判断是否是单例
                        if (loadedClass.isAnnotationPresent(Scope.class)){
                            Scope scope = loadedClass.getAnnotation(Scope.class);
                            String value = scope.value();
                            beanDefinition.setScope(value);
                        }else {
                            // 默认单例
                            beanDefinition.setScope("singleton");
                        }
                        //存到map中
                        beanDefinitionMap.put(beanName,beanDefinition);
                    }

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }

            }
        }

    }
}

/**
 * 这里返回bean实例
 * @param beanName
 * @return
 */
public Object getBean(String beanName){
    // 首先判断是否在已扫描的存入map中 不存在抛出异常
    if (!beanDefinitionMap.containsKey(beanName)){
        throw new NullPointerException();
    }

    BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); //获取beanDefinition
    // 判断是否单例
    if (beanDefinition.getScope().equals("singleton")) {
        // 如果是单例就从单例池map中取出
        Object singleton = singletonDefinitions.get(beanName);
        // 2.2 这里有个问题如果orderService是原型的那么在单例池就获取不到,我们就要创建bean保存到单例池中
        if (singleton == null){
            Object bean = createBean(beanName,beanDefinition);
            singletonDefinitions.put(beanName,bean);
        }
        return singleton;
    }else {
        // 原型 每次都创建
        Object  protoType = createBean(beanName, beanDefinition);
        return protoType;
    }
}

}
`
实现了spring的依赖注入和还未实现inilizingBean和BeanPostProcessor不过都是简单了,aop实在BeanPostProcessor的初始化方法后那个方法执行的可以使用CJLIB或者动态代理,动态代理需要父接口,CJLIB只需要继承被代理对象就可