Skip to content

Latest commit

 

History

History
271 lines (200 loc) · 7.15 KB

07.用30个类高仿真提炼纯手写Spring框架V2.0之IOC与DI.md

File metadata and controls

271 lines (200 loc) · 7.15 KB

30个类提炼Spring-SpringIOC/DI

image-20220221234215031

1.从Servlet到ApplicationContext

image-20211230214751359

image-20211230215723075

BeanFactory

public interface STBeanFactory {

    /**
     * 根据beanName从IOC容器获得一个实例bean
     * @param beanName
     * @return
     */
    Object getBean(String beanName);

}

FactoryBean

public interface STFactoryBean {


}

ApplicationContext

public class STApplicationContext extends STDefaultListableBeanFactory implements STBeanFactory {

    private String[] configLocations;

    private STBeanDefinitionReader reader;
    
    public STApplicationContext(String... configLocations) {
        this.configLocations = configLocations;
        refresh();
    }

    @Override
    public void refresh() {
        // 1.定位,定位配置文件
        reader = new STBeanDefinitionReader(configLocations);

        // 2.加载配置文件,扫描相关的类,把它们封装成BeanDefinition
        List<STBeanDefinition> beanDefinitionList = reader.loadBeanDefinitions();

        // 3.注册,把配置信息放到容器里面(伪IOC容器)
        doRegistryBeanDefinition(beanDefinitionList);

        // 4.把不是延迟加载的类,提前初始化
        doAutowired();
    }

    // 只处理非延时加载的情况
    private void doAutowired() {
        for (Map.Entry<String, STBeanDefinition> beanDefinitionEntry : super.beanDefinitionMap.entrySet()) {
            String beanName = beanDefinitionEntry.getKey();
            if (!beanDefinitionEntry.getValue().isLazyInit()) {
                getBean(beanName);
            }
        }
    }

    private void doRegistryBeanDefinition(List<STBeanDefinition> beanDefinitionList) {
        for (STBeanDefinition beanDefinition : beanDefinitionList) {
            this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(), beanDefinition);
        }
    }

    @Override
    public Object getBean(String beanName) {

        // 1.初始化
        instantiateBean(beanName, new STBeanDefinition());


        // 2.注入
        populateBean(beanName, new STBeanDefinition(), new STBeanWrapper());


        return null;
    }

    private void populateBean(String beanName, STBeanDefinition stBeanDefinition, STBeanWrapper stBeanWrapper) {
    }

    private void instantiateBean(String beanName, STBeanDefinition stBeanDefinition) {
    }
    
}

AbstractApplicationContext

public abstract class STAbstractApplicationContext {

    /**
     * 受保护,只提供子类重写
     */
    protected void refresh(){}
}

DefaultListableBeanFactory

 /** Map of bean definition objects, keyed by bean name */
    //存储注册信息的BeanDefinition
    protected final Map<String, STBeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

BeanDefinition

public class STBeanDefinition {

    private String beanClassName;

    private boolean lazyInit = false;

    private String factoryBeanName;
}

ApplicationContextAware

public interface STApplicationContextAware {
    void setApplicationContext(STApplicationContext applicationContext);
}

BeanDefinitionReader

public class STBeanDefinitionReader {

    private Properties config = new Properties();

    // 固定配置文件中的key
    private final String SCAN_PACKAGE = "scanPackage";

    private List<String> registryBeanClasses = new ArrayList<>();



    public STBeanDefinitionReader(String... locations) {
        // 通过URL定位找到其对应的文件,然后转为文件流
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath", ""));
        try {
            config.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        doScanner(config.getProperty(SCAN_PACKAGE));

    }

    private void doScanner(String scanPackage) {
        // 转为文件路径,实际上把.换成/就可以了
        URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());
        for (File file: classPath.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanPackage + "." + file);
            } else {
                if (file.getName().endsWith(".class")) {
                    continue;
                }
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                registryBeanClasses.add(className);
            }
        }
    }

    public Properties getConfig() {
        return this.config;
    }

    // 把配置文件中扫描的所有配置信息转换为STBeanDefinition对象,以便IOC操作方便
    public List<STBeanDefinition> loadBeanDefinitions(String... locations) {
        List<STBeanDefinition> result = new ArrayList<>();

        for (String className : registryBeanClasses) {
            STBeanDefinition beanDefinition = doCreateBeanDefinition(className);
            if (null == beanDefinition) { continue; }
            result.add(beanDefinition);
        }
        return result;

    }

    // 把没一个配置信息解析称一个BeanDefinition
    private STBeanDefinition doCreateBeanDefinition(String className) {
        try {
            Class<?> beanClass = Class.forName(className);

            // 有可能是一个接口,用他的实现类作为beanClassName
            if (beanClass.isInterface()) {
                return null;
            }
            STBeanDefinition stBeanDefinition = new STBeanDefinition();
            stBeanDefinition.setBeanClassName(className);
            stBeanDefinition.setFactoryBeanName(beanClass.getSimpleName());
            return stBeanDefinition;
        } catch (Exception e) {

        }
        return null;
    }

    /**
     * 默认不存在类名首字母小写的情况
     * @param simpleName
     * @return
     */
    private String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        // 之所以加32,是因为大小写字母恶ASCII码相差32
        // 而且大写字母的ASCII码小于小写字母的ASCII码
        // 在Java中,对char作算学运算,实际上就是对ASCII码做运算
        chars[0] += 32;
        return String.valueOf(chars);
    }
}

STBeanWrapper

public class STBeanWrapper {
    /**
     * Return the bean instance wrapped by this object.
     */
    public Object getWrappedInstance() {
        return null;
    }

    /**
     * Return the type of the wrapped bean instance.
     */
    public Class<?> getWrappedClass() {
        return null;
    }
}