栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

简单模拟手写Spring框架

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

简单模拟手写Spring框架

只是简单的按照Spring的执行流程写了一下代码,当然跟Spring源码是有很大的差别,可以拿来学习,不喜勿碰。支持单例和原型的bean,以及初始化前、初始化、初始化后的方法执行,可以解析各种定义的注解

执行流程

工程机构 

 

关键代码,代码路径:xqc-structure: 模拟手写spring

package com.xqc.context;

import com.xqc.annotation.*;
import com.xqc.aware.XqcBeanAware;
import com.xqc.aware.XqcBeanPostProcessor;
import com.xqc.aware.XqcInitializingBean;
import com.xqc.definition.XqcBeanDefinition;
import com.xqc.enums.ScopeEnum;
import com.xqc.exception.ThrowUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class XqcApplicationContext {

    //bean定义
    private static final Map beanDefinitions = new HashMap<>();
    //单例bean池
    private static final Map singletonObjects = new HashMap<>();
    //bean后置处理器
    private static final List beanPostProcessors = new linkedList<>();

    public XqcApplicationContext(Class clazz){
        if (!clazz.isAnnotationPresent(XqcConfiguration.class)) {
            ThrowUtils.throwEx("扫描配置不正确");
        }
        //1、解析入口配置类,生成扫描路径
        String packagePath = getPackagePath(clazz);
        //2、扫描包,生成beanDefinitions
        scan(packagePath);
        //3、解析和生成bean
        this.refresh();
    }

    private void refresh(){
        for (Map.Entry entry : beanDefinitions.entrySet()) {
            String beanName = entry.getKey();
            XqcBeanDefinition xqcBeanDefinition = entry.getValue();
            if (ScopeEnum.PROTOTYPE.getCode().equals(xqcBeanDefinition.getScope())) {
                continue;
            }
            //实例化,生成bean对象
            Object bean = createBean(beanName, xqcBeanDefinition);
            //放入map
            singletonObjects.put(beanName,bean);
        }
    }

    
    private void scan(String packagePath) {
        //2、根据路径扫描文件,获取class
        List classes = new ArrayList<>();
        scannerPackage(classes,packagePath);
        for (String class1 : classes) {
            try {
                //加载成class方便后续判断
                Class aClass = XqcApplicationContext.class.getClassLoader().loadClass(subPath(class1));
                //是否有XqcComponent注解
                if(!aClass.isAnnotationPresent(XqcComponent.class)){
                    continue;
                }
                //是否实现XqcBeanPostProcessor接口
                if(XqcBeanPostProcessor.class.isAssignableFrom(aClass)){
                    Object instance = aClass.getConstructor().newInstance();
                    beanPostProcessors.add((XqcBeanPostProcessor) instance);
                }
                XqcBeanDefinition beanDefinition = new XqcBeanDefinition();
                //获取bean名称
                String beanName = getBeanName(aClass);
                beanDefinition.setClazz(aClass);
                beanDefinition.setBeanName(beanName);
                //解析XqcScope注解
                if(aClass.isAnnotationPresent(XqcScope.class)){
                    XqcScope xqcScopeAnnotation = aClass.getAnnotation(XqcScope.class);
                    if(!ScopeEnum.PROTOTYPE.getCode().equals(xqcScopeAnnotation.value())
                            && !ScopeEnum.SINGLETON.getCode().equals(xqcScopeAnnotation.value())){
                        ThrowUtils.throwEx("bean scope类型不正确");
                    }
                    beanDefinition.setScope(xqcScopeAnnotation.value());
                }else{
                    //没有写默认单例
                    beanDefinition.setScope(ScopeEnum.SINGLETON.getCode());
                }

                //生成beanDefinition
                beanDefinitions.put(beanName,beanDefinition);

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

    
    private String getBeanName(Class aClass) {
        XqcComponent xqcComponentAnnotation = aClass.getAnnotation(XqcComponent.class);
        String beanName = xqcComponentAnnotation.value();
        if(beanName != null && !"".equals(beanName.trim())){
            return beanName;
        }
        //使用类名,首字母小写
        String simpleName = aClass.getSimpleName();
        return simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1, simpleName.length());
    }

    
    private String getPackagePath(Class clazz) {
        XqcConfiguration configurationAnnotation = clazz.getAnnotation(XqcConfiguration.class);
        //获取要扫描的路径
        String packages = configurationAnnotation.value();
        packages = packages.replace(".","/");
        //读取包下面的class,真正的Spring源码用的ASM技术,这里只是简单的实现读取
        ClassLoader classLoader = XqcApplicationContext.class.getClassLoader();
        return classLoader.getResource(packages).getFile();
    }

    
    private String subPath(String path) {
        path = path.substring(path.indexOf("classes") + 8, path.indexOf(".class")).replace("\",".");
        return path;
    }

    
    private static void scannerPackage(List classes, String path) {
        File file = new File(path);
        for (File file1 : file.listFiles()) {
            if (file1.isDirectory()) {
                scannerPackage(classes,file1.getPath());
            } else {
                classes.add(file1.getPath());
            }
        }
    }

    
    public Object createBean(String beanName,XqcBeanDefinition beanDefinition){
        Object bean = null;
        try {
            Class clazz = beanDefinition.getClazz();
            bean = clazz.newInstance();

            //初始化前
            for (XqcBeanPostProcessor beanPostProcessor : beanPostProcessors) {
                bean = beanPostProcessor.postProcessBeforeInitialization(bean,beanName);
            }

            for (Field field : clazz.getDeclaredFields()) {
                //解析XqcValue注解
                if (field.isAnnotationPresent(XqcValue.class)) {
                    XqcValue xqcValueAnnotation = field.getAnnotation(XqcValue.class);
                    field.setAccessible(true);
                    field.set(bean, xqcValueAnnotation.value());
                }
                //解析XqcAutowired注解
                if (field.isAnnotationPresent(XqcAutowired.class)) {
                    Object bean1 = getBean(field.getType());
                    field.setAccessible(true);
                    field.set(bean, bean1);
                }
            }
            //解析aware接口
            if (bean instanceof XqcBeanAware) {
                ((XqcBeanAware) bean).setBeanName(beanName);
            }

            //解析XqcPostConstruct注解的方法
            for (Method method : clazz.getDeclaredMethods()) {
                //解析XqcValue注解
                if (method.isAnnotationPresent(XqcPostConstruct.class)) {
                    method.invoke(bean,  method.getTypeParameters());
                }
            }

            //bean初始化执行
            if (bean instanceof XqcInitializingBean) {
                ((XqcInitializingBean) bean).afterPropertiesSet();
            }

            //初始化后
            for (XqcBeanPostProcessor beanPostProcessor : beanPostProcessors) {
                bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }

    
    public Object getBean(String beanName){
        XqcBeanDefinition xqcBeanDefinition = beanDefinitions.get(beanName);
        if(xqcBeanDefinition == null){
            ThrowUtils.throwEx("bean对象不存在");
        }
        String scope = xqcBeanDefinition.getScope();
        if(ScopeEnum.PROTOTYPE.getCode().equals(scope)){
            //原型,每次都创建
            return this.createBean(beanName,beanDefinitions.get(beanName));
        }
        if(singletonObjects.containsKey(beanName)){
            return singletonObjects.get(beanName);
        }
        return this.createBean(beanName, beanDefinitions.get(beanName));
    }

    public Object getBean(Class clazz){
        return this.getBean(this.getBeanName(clazz));
    }

}

测试工程,引入上面的xqc-beans工程的jar包

结果输出 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/333024.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号