Loading

02_手写模拟Spring底层原理

参考spring的使用方式:

		// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();

设计模拟spring使用方式:

新增spring包:

新增YyjApplicationContext模拟spring启动类,新增构造方法和getBean方法:

public class YyjApplicationContext {

    private Class configClass;

    public YyjApplicationContext(Class configClass) {
        this.configClass = configClass;
    }

    public Object getBean(String beanName) {
        
    }
}

新增扫描方法扫描bean,并放入beanDefinitionMap中用于后期创建bean,在构造方法中调用scan()方法:

private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

private void scan(Class configClass) {
        // 从ComponentScan中拿到扫描路径
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();
            path = path.replace(".", "/");  // com/yyj/service
            // 拿到自己的类加载器,用来加载扫描路径下的bean
            ClassLoader classLoader = YyjApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);
            if (resource == null) {
                return;
            }
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                for (File f : Objects.requireNonNull(file.listFiles())) {
                    String absolutePath = f.getAbsolutePath();
                    // 所有的.class文件的路径如:com\yyj\service\OrderService
                    absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                    absolutePath = absolutePath.replace("\\", ".");
                    try {
                        // 加载类
                        Class<?> clazz = classLoader.loadClass(absolutePath);
                        if (clazz.isAnnotationPresent(Component.class)) {
                            Component componentAnnotation = clazz.getAnnotation(Component.class);
                            String beanName = componentAnnotation.value();
                            if ("".equals(beanName)) {
                                beanName = Introspector.decapitalize(clazz.getSimpleName());
                            }
                            BeanDefinition beanDefinition = new BeanDefinition();
                            beanDefinition.setType(clazz);
                            if (clazz.isAnnotationPresent(Scope.class)) {
                                Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
                                String value = scopeAnnotation.value();
                                beanDefinition.setScope(value);
                            } else {
                                beanDefinition.setScope("singleton");
                            }
                            beanDefinitionMap.put(beanName, beanDefinition);
                        }
                    } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
                             InstantiationException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

createBean的核心逻辑:

private Object createBean(String beanName, BeanDefinition beanDefinition) {
        Class clazz = beanDefinition.getType();
        Object instance = null;
        try {
            // 创建实例
            instance = clazz.getConstructor().newInstance();
            // 依赖注入逻辑
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    field.setAccessible(true);
                    field.set(instance, getBean(field.getName()));
                }
            }
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException e) {
            e.printStackTrace();
        }
        return instance;
    }

构造方法中将扫描到单例bean的BeanDefinition进行创建到并放到单例池中:

private final Map<String, Object> singletonObjects = new HashMap<>();

for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();
            BeanDefinition beanDefinition = entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, bean);
            }
        }

从容器中获取bean的核心逻辑getBean方法:

    public Object getBean(String beanName) {
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new NullPointerException();
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        // 单例bean
        if (beanDefinition.getScope().equals("singleton")) {
            Object singletonBean = singletonObjects.get(beanName);
            // 若还未创建时就获取,就先创建
            if (singletonBean == null) {
                singletonBean = createBean(beanName, beanDefinition);
                singletonObjects.put(beanName, singletonBean);
            }
            return singletonBean;
        } else {
            // 原型
            return createBean(beanName, beanDefinition);
        }
    }

bean的扩展点BeanPostProcessor的核心逻辑:

增加接口:

package com.spring;

public interface BeanPostProcessor {

    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

 在扫描过程中将扫描到的BeanPostProcessor添加到beanPostProcessorList中:

    private final List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

    // 判断一个类是否实现了BeanPostProcessor接口
    if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
        BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
        beanPostProcessorList.add(instance);
    }

在创建bean的过程中执行扩展点beanPostProcessorList中的逻辑:

// bean的前置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
    instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}

// bean的后置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
    instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}

扩展点InitializingBean的实现:

新增接口InitializingBean:

package com.spring;

public interface InitializingBean {
    void afterPropertiesSet();
}

扫描到的bean若实现了该接口则会在创建过程中执行该实现方法:

// bean的前置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
    instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
// 初始化
if (instance instanceof InitializingBean) {
    ((InitializingBean) instance).afterPropertiesSet();
}
// bean的后置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
    instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}

Aware 回调方法的实现以BeanNameAware为例:

增加接口BeanNameAware:

package com.spring;

public interface BeanNameAware {

    void setBeanName(String name);
}

扫描到的bean若实现了该接口则在创建bean的过程中会执行该接口实现方法的逻辑并将beaname作为参数:

// Aware 回调方法
if (instance instanceof BeanNameAware) {
    ((BeanNameAware) instance).setBeanName(beanName);
}
// bean的前置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
    instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
// 初始化
if (instance instanceof InitializingBean) {
    ((InitializingBean) instance).afterPropertiesSet();
}
// bean的后置处理
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
    instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}

 

posted @ 2023-08-17 23:24  1640808365  阅读(13)  评论(0编辑  收藏  举报