主要方向

  • 了解Spring底层源码的启动过程
  • 了解BeanDefinition、BeanPostProcessor的概念
  • 了解Spring解析配置类等底层源码工作流程
  • 了解依赖注入、Aware回调等底层源码工作流程
  • 了解Spring AOP的底层源码工作流程

    大致实现生命周期

  • 类通过无参构造实例化

  • 依赖注入
  • Aware接口回调
  • 初始化前: 实现BeanPostProcessor.postProcessBeforeInitialization
  • 初始化前: 调用@PostConstruct注解的方法
  • 初始化: 实现InitializingBean.afterPropertiesSet
  • 初始化后: 实现BeanPostProcessor.postProcessAfterInitialization
  • 初始化后: BeanPostProcessor(Aop—>代理对象)
  • Bean对象

    手写模拟Spring

    前期准备

    1. @Retention(RetentionPolicy.RUNTIME)
    2. @Target(ElementType.TYPE)
    3. public @interface Component {
    4. String name() default "";
    5. }
    1. @Retention(RetentionPolicy.RUNTIME)
    2. @Target(ElementType.TYPE)
    3. public @interface ComponentScan {
    4. String[] basePackages() default {};
    5. }
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD, ElementType.METHOD})
    public @interface Autowired {
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface Scope {
     String value() default "singleton";
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface PostConstruct {
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface Value {
     String value() default "";
    }
    

    ```java public class BeanDefinition {

    private Class<?> clazz; /**

    • 作用域: singleton
    • prototype */ private String scope;
public Class<?> getClazz() {
    return clazz;
}

public void setClazz(Class<?> clazz) {
    this.clazz = clazz;
}

public String getScope() {
    return scope;
}

public void setScope(String scope) {
    this.scope = scope;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    BeanDefinition that = (BeanDefinition) o;
    return Objects.equals(clazz, that.clazz) && Objects.equals(scope, that.scope);
}

@Override
public int hashCode() {
    return Objects.hash(clazz, scope);
}

}

```java
public interface BeanPostProcessor {
    /**
     * 该方法在bean实例化完毕(且已经注入完毕),在afterPropertiesSet或自定义init方法执行之前
     */
    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    /**
     * 在afterPropertiesSet或自定义init方法执行之后
     */
    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}
public interface InitializingBean {
    void afterPropertiesSet();
}
public interface BeanNameAware {
    void setBeanName(String beanName);
}

实现包扫描逻辑

public class AnnotationConfigApplicationContext {
    /**
     * 配置类
     */
    private final Class<?> configClass;
    /**
     * key:beanName, value:BeanDefinition
     * 专门用来存储扫描到的BeanDefinition
     */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    /**
     * 继承了BeanPostProcessor的类
     */
    private final List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    /**
     * 扫描到的class文件
     */
    private final List<File> scannedFiles = new ArrayList<>();
    /**
     * 单例池
     */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    public AnnotationConfigApplicationContext(Class<?> configClass) {
        this.configClass = configClass;
        // 进行包扫描
        scan(configClass);
    }

    /**
     * 扫描包路径下加了@Component注解的放到beanDefinitionMap
     */
    private void scan(Class<?> configClass) {
        // 如果配置类加上了@ComponentScan
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            // 从注解上拿到需要扫描的包路径basePackages
            ComponentScan componentScan = configClass.getAnnotation(ComponentScan.class);
            String[] basePackages = componentScan.basePackages();
            // 遍历包路径,通过io去拿到所有class文件
            for (String basePackage : basePackages) {
                // 扫描包
                // 找到包路径下的所有class,解析class得到BeanDefinition
                scanCandidateComponents(basePackage);
            }
        }
    }

    /**
     * 扫描包路径下的class文件并且解析,如果有@Component就进行解析成BeanDefinition
     */
    private void scanCandidateComponents(String basePackage) {
        // 获取包路径下的文件
        // 判断当前是否是目录,如果是目录就递归去获取class文件,这里我们需要把这些扫描到的class文件保存下来
        listPackageFiles(getPackageFile(basePackage));
        // 遍历扫描到的文件找出class文件,判断class文件中有没有@Component,如果有就看是单例还是原型的
        composeBeanDefinition(scannedFiles);
    }


    /**
     * 构建BeanDefinition
     */
    private void composeBeanDefinition(List<File> scannedFiles) {
        // 遍历扫描到的文件找出class文件
        for (File f : scannedFiles) {
            // 获取f的绝对路径
            String absolutePath = f.getAbsolutePath();
            // 判断是否是class文件
            if (absolutePath.contains(".class")) {
                // 根据不同操作系统,获取指定的二进制名称
                String binaryName = getBinaryName(absolutePath);
                try {
                    // 通过当前类加载器加载二进制名称
                    Class<?> clazz = this.getClass().getClassLoader().loadClass(binaryName);
                    // 判断该类是否有@Component
                    if (clazz.isAnnotationPresent(Component.class)) {
                        // 这里我们要考虑判断有没有继承BeanPostProcessor,如果有那么就把这些类放到beanPostProcessorList里缓存下来
                        if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
                            BeanPostProcessor beanPostProcessor = (BeanPostProcessor) clazz.getConstructor().newInstance();
                            beanPostProcessorList.add(beanPostProcessor);
                        }
                        // 拿到当前类的@Component的注解信息beanName
                        Component component = clazz.getAnnotation(Component.class);
                        String beanName = component.name();
                        // 如果beanName不填写,就默认用类名生成小写
                        if ("".equals(beanName)) {
                            beanName = Introspector.decapitalize(clazz.getSimpleName());
                        }
                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setClazz(clazz);
                        // 判断bean是否是单例的,如果有值就按照传递的否则按照单例默认值进行
                        if (clazz.isAnnotationPresent(Scope.class)) {
                            Scope scope = clazz.getAnnotation(Scope.class);
                            beanDefinition.setScope(scope.value());
                        } else {
                            // 默认使用singleton
                            beanDefinition.setScope("singleton");
                        }
                        // 将beanDefinition放入beanDefinitionMap
                        beanDefinitionMap.put(beanName, beanDefinition);
                    }
                } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }


   /**
     * 根据不同操作系统,获取指定的二进制名称
     */
    private String getBinaryName(String absolutePath, boolean isMaven) {
        String os = System.getProperty("os.name");
        String path;
        if (isMaven) {
            if (os.startsWith("Windows")) {
                path = "target\\classes";
                absolutePath = absolutePath.substring(absolutePath.indexOf(path) + path.length() + 1, absolutePath.indexOf(".class"));
                absolutePath = absolutePath.replace("\\", ".");
            } else {
                path = "target/classes";
                absolutePath = absolutePath.substring(absolutePath.indexOf(path) + path.length() + 1, absolutePath.indexOf(".class"));
                absolutePath = absolutePath.replace("/", ".");
            }
        } else {
            // gradle
            if (os.startsWith("Windows")) {
                path = "out\\production\\classes";
                absolutePath = absolutePath.substring(absolutePath.indexOf(path) + path.length() + 1, absolutePath.indexOf(".class"));
                absolutePath = absolutePath.replace("\\", ".");
            } else {
                path = "out/production/classes";
                absolutePath = absolutePath.substring(absolutePath.indexOf(path) + path.length() + 1, absolutePath.indexOf(".class"));
                absolutePath = absolutePath.replace("/", ".");
            }
        }
        return absolutePath;
    }


    /**
     * 列举出file下的所有class文件
     */
    private void listPackageFiles(File file) {
        // 判断当前是否是目录
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            assert files != null;
            if (files.length == 0) {
                return;
            }
            for (File f : files) {
                scannedFiles.add(f);
                // 判断当前是否是目录
                if (f.isDirectory()) {
                    // 继续递归获取f下的class文件
                    listPackageFiles(f);
                }
            }
        }
    }


    /**
     * 获取包路径下的文件
     */
    private File getPackageFile(String basePackage) {
        // 这里想到我们指定的路径linc.cool,我们要转变成linc/cool,所以需要替换
        String path = basePackage.replace(".", "/");
        // 通过类加载器去获取path路径下的文件
        URL resource = this.getClass().getClassLoader().getResource(path);
        assert resource != null;
        return new File(resource.getFile());
    }

}

实现创建Bean

/**
     * 获取Bean
     */
    public Object getBean(String beanName) {
        // 判断这个beanName在beanDefinitionMap中是否存在
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new NullPointerException(String.format("%s不存在", beanName));
        }
        // 存在就拿出beanDefinition
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        // 如果是单例就返回单例池中的对象,否则返回新的实例
        if ("singleton".equals(beanDefinition.getScope())) {
            Object singletonBean = singletonObjects.get(beanName);
            // 如果没有就进行创建单例Bean
            if (singletonBean == null) {
                singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
            return singletonBean;
        }
        // 原型Bean就直接创建
        return createBean(beanName, beanDefinition);
    }

    /**
     * 创建Bean
     */
    private Object createBean(String beanName, BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getClazz();
        try {
            Object bean = beanClass.getConstructor().newInstance();

            // 如果对象有属性加了@Autowired注解的,就给它进行赋值
            for (Field f : beanClass.getDeclaredFields()) {
                if (f.isAnnotationPresent(Autowired.class)) {
                    f.setAccessible(true);
                    // 去单例池中找Bean,如果没有就创建
                    f.set(bean, getBean(f.getName()));
                }
            }

            // Aware回调接口
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }

            // 初始化前: 实现BeanPostProcessor.postProcessBeforeInitialization
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
            }

            // 初始化前: 调用@PostConstruct注解的方法
            for (Method method : beanClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(PostConstruct.class)) {
                    method.setAccessible(true);
                    method.invoke(bean);
                }
            }

            // 初始化: 实现InitializingBean.afterPropertiesSet
            if (bean instanceof InitializingBean) {
                ((InitializingBean) bean).afterPropertiesSet();
            }

            // 初始化后: 实现BeanPostProcessor.postProcessAfterInitialization
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName);
            }

            // 初始化后: BeanPostProcessor(Aop-->代理对象)

            return bean;

        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 注册单例beanDefinition到单例池
     */
    private void registerBean() {
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();
            BeanDefinition beanDefinition = entry.getValue();
            // 如果是单例我们就创建bean,放到单例池
            if ("singleton".equals(beanDefinition.getScope())) {
                singletonObjects.put(beanName, createBean(beanName, beanDefinition));
            }
        }
    }

实现@Value的填充功能

@Component
public class ValueAnnotationBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        // 遍历所有field,判断是否加了@Value,有就进行填充
        Stream.of(bean.getClass().getDeclaredFields()).forEach(field -> {
            if (field.isAnnotationPresent(Value.class)) {
                String value = field.getAnnotation(Value.class).value();
                // 如果是字符串,就进行填充
                if (!"".equals(value)) {
                    try {
                        field.setAccessible(true);
                        field.set(bean, field.getAnnotation(Value.class).value());
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        return bean;
    }
}

目前我们只是实现了填充字符串的功能,怎么实现@Value的依赖注入的功能呢? 这部分逻辑和@Autowired实现很相似

    // 如果对象有属性加了@Autowired注解的,就给它进行赋值
            for (Field f : beanClass.getDeclaredFields()) {
                if (f.isAnnotationPresent(Autowired.class)) {
                    f.setAccessible(true);
                    // 去单例池中找Bean,如果没有就创建
                    f.set(bean, getBean(f.getName()));
                } else if (f.isAnnotationPresent(Value.class)) {
                    String value = f.getAnnotation(Value.class).value();
                    if ("".equals(value)) {
                        f.setAccessible(true);
                        // 去单例池中找Bean,如果没有就创建
                        f.set(bean, getBean(f.getName()));
                    }
                }
            }