Spring的核心思想其中之一就是IOC,也就是依赖倒转

通俗的解释起来就是,我们将自己所需要的Bean对象在配置文件中写好其定义,配置好依赖注入等信息(他所需要的依赖)

由Spring负责创建该Bean,用的时候也直接从Spring来拿

这里记录一下简单的一个IOC容器的实现

Bean的定义

Spring的Bean定义一般通过Xml配置文件来实现,这里就不用Xml了,就用最简单的properties吧

userDao=UserDao

Key表示为bean的名字,Value表示为bean的全限定类名

另外再来一个对应的BeanDefinition类

public class BeanDefinition {
    private String beanName;
    private Class beanClass;
    // 省略 getter setter
}

资源加载器

负责读取我们的配置文件,来加载bean信息入内存

public class ResourceLoader {
    public static Map<String, BeanDefinition> loadBeans() {
        Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(16);
        Properties properties = new Properties();
        try {
            // 读取properties文件,获取所有的文字描述的bean definition
            InputStream inputStream = ResourceLoader.class.getResourceAsStream("/beans.properties");
            properties.load(inputStream);
            Iterator<String> it = properties.stringPropertyNames().iterator();
            while (it.hasNext()) {
                String key = it.next();
                String className = properties.getProperty(key);
                
                // 创建bean definition
                BeanDefinition beanDefinition = new BeanDefinition();
                beanDefinition.setBeanName(key);
                Class clazz = Class.forName(className);
                beanDefinition.setBeanClass(clazz);
                // 放入map中保存
                beanDefinitionMap.put(key, beanDefinition);
            }
            inputStream.close();
        } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
        }
        return beanDefinitionMap;
    }
}

Bean注册器

创建一个注册器,用来保存所有的单例Bean

public class BeanRegister {
    // IOC容器
    private Map<String, Object> iocContainer = new HashMap<>(32);

    // 获取单例Bean
    public Object getSingletonBean(String beanName) {
        return iocContainer.get(beanName);
    }

    // 注册单例bean
    public void registerSingletonBean(String beanName, Object bean) {
        if (iocContainer.containsKey(beanName)) {
            return;
        }
        iocContainer.put(beanName, bean);
    }
}

BeanFactory

这里实现一个并夕夕版BeanFactory,用它来完成对Bean的获取与管理

它负责实现从配置文件读取bean definition信息,然后使用BeanRegister来注册bean到容器中

public class BeanFactory {

    private Map<String, BeanDefinition> beanDefinitionMap;

    private BeanRegister beanRegister;

    public BeanFactory() {
        beanRegister = new BeanRegister();
        beanDefinitionMap = ResourceLoader.loadBeans();
    }


    public Object getBean(String beanName) {
        // 从bean容器中获取
        Object bean = beanRegister.getSingletonBean(beanName);
        if (bean != null)
            return bean;
        // 如果没有的话, 就获取bean的定义信息, 创建bean后加入容器, 实现单例模式
        createBean(beanDefinitionMap.get(beanName));
        return beanRegister.getSingletonBean(beanName);
    }


    private void createBean(BeanDefinition beanDefinition) {
        String beanName = beanDefinition.getBeanName();
        Class beanClass = beanDefinition.getBeanClass();
        try {
            // 使用反射来创建bean, 并加入容器中
            beanClass.newInstance();
            beanRegister.registerSingletonBean(beanName, beanClass.newInstance());
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

测试一下

实体类

public class UserDao {

    public void queryUserInfo(){
        System.out.println("A good man.");
    }
}

测试

public class Test {
    public static void main(String[] args) {
        BeanFactory beanFactory = new BeanFactory();
        UserDao userDao = (UserDao) beanFactory.getBean("userDao");
        UserDao userDao1 = (UserDao) beanFactory.getBean("userDao");
        userDao.queryUserInfo();
        System.out.println(userDao == userDao1);
    }
}

最终打印结果

A good man.
true

可以发现实现了单例模式的并夕夕版IOC就已经实现成功了

Last modification:April 16th, 2022 at 05:52 pm