简易ioc容器实现

package com.summer.simplespringioc.model;

import lombok.Data;

/**
 * bean property配置
 *
 * @author summer
 * @version $Id: BeanPropertyConfig.java, v 0.1 2022年02月14日 9:27 AM summer Exp $
 */
@Data
public class BeanPropertyConfig {
    //属性名
    private String name;
    //属性值
    private String value;
    //属性的值是否引用其他bean
    private Boolean isValueRef;
}
package com.summer.simplespringioc.model;

import lombok.Data;

/**
 * constructor arg配置
 *
 * @author summer
 * @version $Id: ConstructorPropertyConfig.java, v 0.1 2022年02月14日 9:27 AM summer Exp $
 */
@Data
public class ConstructorPropertyConfig {
    //属性值
    private String value;
    //属性的值是否引用其他bean
    private Boolean isValueRef;
}
package com.summer.simplespringioc.util;

import org.apache.commons.lang3.StringUtils;

/**
 * 基础工具类
 *
 * @author summer
 * @version $Id: BaseUtils.java, v 0.1 2022年02月27日 5:29 PM summer Exp $
 */
public class BaseUtils {

    /**
     * 首字符大写
     *
     * @param s 字符串
     * @return
     */
    public final static String upperFirstChar(String s) {
        if (StringUtils.isBlank(s)) {
            return s;
        }

        char chars[] = s.toCharArray();
        chars[0] = Character.toUpperCase(s.charAt(0));
        return new String(chars);
    }

    /**
     * 将字符串类型的值转换为特定基础类型的值
     *
     * @param s
     * @return
     */
    public final static Object convertBaseDataType(String s, String type) {
        if (StringUtils.equals("java.lang.Integer", type)) {
            return Integer.valueOf(s);
        } else if (StringUtils.equals("java.lang.Long", type)) {
            return Long.valueOf(s);
        } else if (StringUtils.equals("java.lang.Double", type)) {
            return Double.valueOf(s);
        } else if (StringUtils.equals("java.lang.String", type)) {
            return s;
        }

        return null;
    }
}
package com.summer.simplespringioc;

import com.summer.simplespringioc.model.BeanPropertyConfig;
import com.summer.simplespringioc.model.ConstructorPropertyConfig;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * bean定义领域模型
 *
 * @author summer
 * @version $Id: SimpleBeanDefinition.java, v 0.1 2022年02月10日 9:09 AM summer Exp $
 */
@Data
public class SimpleBeanDefinition {
    private String                          id;
    private String                          className;
    private List<ConstructorPropertyConfig> constructArgs = new ArrayList<>();
    private List<BeanPropertyConfig>        properties    = new ArrayList<>();
}
package com.summer.simplespringioc;

import com.summer.simplespringioc.model.BeanPropertyConfig;
import com.summer.simplespringioc.model.ConstructorPropertyConfig;
import com.summer.simplespringioc.util.BaseUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * spring ioc容器实现
 *
 * @author summer
 * @version $Id: SimpleBeanIocContainer.java, v 0.1 2022年02月10日 9:12 AM summer Exp $
 */
@Slf4j
public class SimpleBeanIocContainer {

    //bean定义相关标签
    private final static String BEAN_CONFIG_ATTR_ID = "id";
    private final static String BEAN_CONFIG_ATTR_CLASS_NAME = "class";
    private final static String BEAN_CONFIG_ATTR_CONSTRUCTOR_ARG = "constructor-arg";
    private final static String BEAN_CONFIG_ATTR_REF = "ref";
    private final static String BEAN_CONFIG_ATTR_PROPERTY = "property";
    private final static String BEAN_CONFIG_ATTR_NAME = "name";
    private final static String BEAN_CONFIG_ATTR_VALUE = "value";
    private final static String BEAN_CONFIG_ATTR_BEAN = "bean";

    /**
     * 存放bean定义的map,key-bean id
     */
    private final Map<String, SimpleBeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

    /**
     * 存放单例bean的本地缓存
     */
    private final Map<String, Object> singletonBeans = new ConcurrentHashMap<>();

    /**
     * 初始化
     *
     * @param file 配置文件
     */
    public void init(String file) {
        //加载xml文件,解析bean的定义
        this.loadBeanDefinitionFromFile(file);

        //注册bean到容器
        registerBean();

        log.info("singletonBeans=" + singletonBeans);
    }

    /**
     * 注册bean到容器
     */
    private void registerBean() {
        for (Map.Entry<String, SimpleBeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanId = entry.getKey();

            getSingletonBean(beanId);
        }
    }

    /**
     * 获取bean(单例)
     *
     * @param beanId bean id
     * @return
     */
    private Object getSingletonBean(String beanId) {
        Object beanObject = singletonBeans.get(beanId);
        if (beanObject != null) {
            return beanObject;
        }

        SimpleBeanDefinition beanDefinition = beanDefinitionMap.get(beanId);
        log.info("create singleton bean begin....beanid=" + beanId + ",beanDefinition=" + beanDefinition);

        beanObject = createBean(beanDefinition);

        singletonBeans.put(beanId, beanObject);

        return beanObject;
    }

    /**
     * 创建bean实例
     *
     * @param beanDefinition
     * @return
     */
    private Object createBean(SimpleBeanDefinition beanDefinition) {
        //初始化bean
        Object beanInstance = initBean(beanDefinition);

        //bean属性注入
        populateBeanProps(beanInstance, beanDefinition);

        return beanInstance;
    }

    /**
     * bean属性注入
     *
     * @param beanInstance bean
     * @param beanDefinition bean定义
     */
    private void populateBeanProps(Object beanInstance, SimpleBeanDefinition beanDefinition) {
        try {
            List<BeanPropertyConfig> propertyConfigs = beanDefinition.getProperties();
            Method[] methods = beanInstance.getClass().getDeclaredMethods();
            for (Method method : methods) {
                for (BeanPropertyConfig beanPropertyConfig : propertyConfigs) {
                    if (StringUtils.equals(method.getName(), "set" + BaseUtils.upperFirstChar(beanPropertyConfig.getName()))) {
                        //通过反射调用set方法进行属性值的设置。有可能是基础类型值,也可能是另一个bean。
                        Object propValue = null;
                        if (beanPropertyConfig.getIsValueRef()) {
                            propValue = getSingletonBean(beanPropertyConfig.getValue());
                        } else {
                            //beanDefinition中存的值是String,需要转换为特定的基础类型
                            Type[] types = method.getParameterTypes();
                            propValue = BaseUtils.convertBaseDataType(beanPropertyConfig.getValue(), types[0].getTypeName());
                        }

                        log.info("method=" + method.getName() + ",propValue=" + propValue + ",beanPropertyConfig=" + beanPropertyConfig + ",beanDefinition=" + beanDefinition);

                        method.invoke(beanInstance, propValue);
                    }
                }
            }
        } catch (Exception e) {
            log.error("populateBeanProps exception,beanDefinition=" + beanDefinition, e);
        }
    }

    /**
     * 初始化bean
     *
     * @param beanDefinition bean定义
     * @return
     */
    private Object initBean(SimpleBeanDefinition beanDefinition) {
        //如果有构造函数配置,调用构造进行实例化
        if (CollectionUtils.isNotEmpty(beanDefinition.getConstructArgs())) {
            return createBeanByConstructor(beanDefinition);
        }

        return createBeanByClassloader(beanDefinition);
    }

    /**
     * 通过构造函数创建bean
     *
     * @param beanDefinition bean定义
     * @return
     */
    private Object createBeanByConstructor(SimpleBeanDefinition beanDefinition) {
        log.info("createBeanByConstructor begin....");
        try {
            Constructor<?> constructor = null;//构造函数匹配
            Object[] args = null;//参数

            Class<?> beanClass = Thread.currentThread().getContextClassLoader().loadClass(beanDefinition.getClassName());
            Constructor<?>[] constructors = beanClass.getDeclaredConstructors();

            //根据构造函数参数长度匹配对应的构造函数
            for (int i = 0;i < constructors.length;++i) {
                Class<?>[] paramTypes = constructors[i].getParameterTypes();
                if (paramTypes.length != beanDefinition.getConstructArgs().size()) {
                    continue;
                }

                constructor = constructors[i];

                //参数组装(可能是基础类型,也可能是bean注入)
                args = new Object[paramTypes.length];
                for (int j = 0;j < beanDefinition.getConstructArgs().size(); ++j) {
                    ConstructorPropertyConfig constructorPropertyConfig = beanDefinition.getConstructArgs().get(j);
                    if (constructorPropertyConfig.getIsValueRef()) {
                        args[j] = getSingletonBean(constructorPropertyConfig.getValue());
                    } else {
                        args[j] = constructorPropertyConfig.getValue();
                    }
                }
                break;
            }

            //创建bean
            return constructor.newInstance(args);
        } catch (Exception e) {
            log.error("createBeanByConstructor exception,beanDefinition=" + beanDefinition);
            return null;
        }
    }

    /**
     * get bean object by bean id
     *
     * @param beanDefinition
     * @return
     */
    public static Object createBeanByClassloader(SimpleBeanDefinition beanDefinition) {
        log.info("createBeanByClassloader begin....");
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            Class<?> clz = classLoader.loadClass(beanDefinition.getClassName());
            return clz.newInstance();
        } catch (Exception e) {
            log.error("createBeanByClassloader exception", e);
            return null;
        }
    }

    /**
     * 解析XML文件加载bean定义
     *
     * @param file 文件名
     */
    private void loadBeanDefinitionFromFile(String file) {
        log.info("loadBeanDefinitionFromFile begin");

        InputStream inputStream = null;
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

            //获取配置文件的文件流
            inputStream = classLoader.getResourceAsStream(file);

            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);

            Element rootElement = document.getRootElement();
            Iterator iterator = rootElement.elementIterator();

            //遍历bean的定义配置
            while (iterator.hasNext()) {
                Element loopElement = (Element) iterator.next();
                String beanId = loopElement.attributeValue(BEAN_CONFIG_ATTR_ID);
                String beanclass = loopElement.attributeValue(BEAN_CONFIG_ATTR_CLASS_NAME);
                if (StringUtils.isBlank(beanId) || StringUtils.isBlank(beanclass)) {
                    log.error("loadBeanDefinitionFromFile xml parse,bean definition illegal:[" + beanId + "," + beanclass + "]");
                    continue;
                }

                //SimpleBeanDefinition构造
                SimpleBeanDefinition simpleBeanDefinition = new SimpleBeanDefinition();
                simpleBeanDefinition.setId(beanId);
                simpleBeanDefinition.setClassName(beanclass);

                //构造函数定义解析
                parseConstructorArg(loopElement, simpleBeanDefinition);

                //property定义解析
                parseProperties(loopElement, simpleBeanDefinition);

                beanDefinitionMap.put(beanId, simpleBeanDefinition);
            }

            log.info("loadBeanDefinitionFromFile,eanDefinitionMap=" + beanDefinitionMap);
        } catch (Exception e) {
            log.error("loadBeanDefinitionFromFile exception,file=" + file, e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("close inputstream exception,file=" + file, e);
                }
            }
        }
    }

    /**
     * get bean definition by bean id
     *
     * @param beanId
     * @return
     */
    public SimpleBeanDefinition getBeanDefinition(String beanId) {
        return beanDefinitionMap.get(beanId);
    }

    /**
     * 构造函数配置解析
     *
     * @param element
     * @param simpleBeanDefinition
     */
    private void parseConstructorArg(Element element, SimpleBeanDefinition simpleBeanDefinition) {
        Iterator iterator = element.elementIterator(BEAN_CONFIG_ATTR_CONSTRUCTOR_ARG);
        while (iterator.hasNext()) {
            Element propertyElement = (Element) iterator.next();
            String ref = propertyElement.attributeValue(BEAN_CONFIG_ATTR_REF);
            String value = propertyElement.attributeValue(BEAN_CONFIG_ATTR_REF);
            if (StringUtils.isBlank(ref) && StringUtils.isBlank(value)) {
                log.error("parseConstructorArg config illegal,propertyElement=" + propertyElement);
                return;
            }

            ConstructorPropertyConfig constructorPropertyConfig = new ConstructorPropertyConfig();
            if (StringUtils.isNotBlank(ref)) {
                constructorPropertyConfig.setValue(ref);
                constructorPropertyConfig.setIsValueRef(true);
            } else {
                constructorPropertyConfig.setValue(value);
            }

            simpleBeanDefinition.getConstructArgs().add(constructorPropertyConfig);
        }
    }

    /**
     * property配置解析
     *
     * @param beanElem
     * @param simpleBeanDefinition
     */
    private void parseProperties(Element beanElem, SimpleBeanDefinition simpleBeanDefinition) {
        Iterator iterator = beanElem.elementIterator(BEAN_CONFIG_ATTR_PROPERTY);
        //遍历所有property配置
        while (iterator.hasNext()) {
            Element propElem = (Element) iterator.next();
            String propertyName = propElem.attributeValue(BEAN_CONFIG_ATTR_NAME);
            if (StringUtils.isBlank(propertyName)) {
                return;
            }

            BeanPropertyConfig beanPropertyConfig = new BeanPropertyConfig();
            beanPropertyConfig.setName(propertyName);

            //property的配置值可能是value也可能是ref
            String value = propElem.attributeValue(BEAN_CONFIG_ATTR_VALUE);
            if (StringUtils.isNotBlank(value)) {
                beanPropertyConfig.setValue(value);
                beanPropertyConfig.setIsValueRef(false);
            } else {
                Iterator propertyRefIterator = propElem.elementIterator(BEAN_CONFIG_ATTR_REF);
                Element refElem = (Element) propertyRefIterator.next();
                String refBean = refElem.attributeValue(BEAN_CONFIG_ATTR_BEAN);
                beanPropertyConfig.setValue(refBean);
                beanPropertyConfig.setIsValueRef(true);
            }

            simpleBeanDefinition.getProperties().add(beanPropertyConfig);
        }
    }
}
package com.summer.simplespringioc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SimplespringiocApplication {

	public static void main(String[] args) {
		SpringApplication.run(SimplespringiocApplication.class, args);
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值