学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • 案例实践

  • 工具使用

  • 项目搭建

  • 服务治理

  • ORM框架

  • MiniSpring

    • Spring IoC-原始Ioc
    • Spring IoC-扩展Bean
      • 一、扩展IoC容器
      • 二、构建单例Bean
        • 1、Bean单例管理接口
        • 2、Bean工厂接口
        • 3、XML解析优化
      • 三、事件监听
      • 四、扩展BeanDefinition
        • 1、BeanDefinition扩展
        • 2、BeanDefinition操作
        • 3、BeanFactory新增接口
        • 4、SimpleBeanFactory具体实现
      • 参考
    • Spring IoC-属性注入
    • Spring Ioc-解决循环依赖
    • Spring Ioc-注解支持
    • Spinrg IoC-IoC完善
  • 案例归档
  • MiniSpring
旭日
2023-05-05
目录

Spring IoC-扩展Bean

# 一、扩展IoC容器

简易IoC容器实现了两个功能:

  • 解析外部资源,将外部资源实例化为BeanDefinition。
  • 遍历BeanDefinition集合,反射加载Bean,注册Bean。

现在需要将这个IoC容器进行如下扩展:

  • 增加单例 Bean 的接口定义,然后把所有的 Bean 默认为单例模式。
  • 预留事件监听的接口,方便后续进一步解耦代码逻辑。
  • 扩展 BeanDefinition,添加一些属性,现在它只有 id 和 class 两个属性,我们要进一步地丰富它。

# 二、构建单例Bean

# 1、Bean单例管理接口

Bean单例接口定义

需要一个接口简单对Bean单例进行管理,包括基本的获取、增加、判断是否存在等操作。

public interface SingletonBeanRegistry {

    /**
     * 注册单例
     * @param beanName Bean id
     * @param singletonObject Bean对象
     */
    void registerSingleton(String beanName, Object singletonObject);

    /**
     * 获取单例
     * @param beanName Bean id
     * @return Bean对象
     */
    Object getSingleton(String beanName);

    /**
     * 是否包含某个单例Bean
     * @param beanName Bean id
     * @return
     */
    boolean containsSingleton(String beanName);

    /**
     * 获取所有单例名称
     * @return
     */
    String[] getSingletonNames();
}

默认Bean单例接口实现

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    /**
     * 存放所有Bean的名称
     */
    protected List<String> beanNames = new ArrayList<>();

    /**
     * Bean单例Map
     */
    protected Map<String, Object> singletons = new ConcurrentHashMap<>();

    @Override
    public void registerSingleton(String beanName, Object singletonObject) {
        synchronized (singletons) {
            singletons.put(beanName, singletonObject);
            beanNames.add(beanName);
        }
    }

    protected void removeSingleton(String beanName) {
        synchronized (singletons) {
            beanNames.remove(beanName);
            singletons.remove(beanName);
        }
    }

    @Override
    public Object getSingleton(String beanName) {
        return singletons.get(beanName);
    }

    @Override
    public boolean containsSingleton(String beanName) {
        return singletons.containsKey(beanName);
    }

    @Override
    public String[] getSingletonNames() {
        return (String[]) this.beanNames.toArray();
    }
}
  • beanNames:存储所有单例Bean的别名。
  • singletons:存储Bean名称和实现类的映射关系。

# 2、Bean工厂接口

Bean工厂接口定义

public interface BeanFactory {

    /**
     * 根据Bean名称,获取Bean对象
     *
     * @param beanName Bean名称
     * @return Bean对象
     * @throws BeansException Bean自定义异常
     */
    Object getBean(String beanName) throws BeansException;

    /**
     * 是否包含某个Bean
     * @param name Bean id
     */
    Boolean containsBean(String name);

    /**
     * 注册单例Bean
     * @param beanName Bean id
     * @param obj Bean对象
     */
    void registerBean(String beanName, Object obj);
}
  • 新增一个判断是否包含Bean方法。
  • 注册方法变为Bean实体注册。

Bean工厂具体实现

public class SimpleBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {

    private Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>(256);

    public SimpleBeanFactory() {

    }

    public void registerBeanDefinition(BeanDefinition beanDefinition) {
        beanDefinitions.put(beanDefinition.getId(), beanDefinition);
    }

    @Override
    public Object getBean(String beanName) throws BeansException {
        // 先尝试直接单例获取
        Object singleton = getSingleton(beanName);
        // 如果没有,开始实例化Bean
        if (singleton == null) {
            // 获取Bean定义
            BeanDefinition beanDefinition = beanDefinitions.get(beanName);
            if (beanDefinition == null) {
                throw new BeansException("错误Bean id");
            }
            try {
                // 反射实例化Bean
                singleton = Class.forName(beanDefinition.getClassName()).newInstance();
                // 注册单例Bean
                registerSingleton(beanName, singleton);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return singleton;
    }

    @Override
    public Boolean containsBean(String name) {
        return containsSingleton(name);
    }

    @Override
    public void registerBean(String beanName, Object obj) {
        registerSingleton(beanName, obj);
    }
}

该类中,由BeanFactory来约束行为,继承DefaultSingletonBeanRegistry来调用具体方法。

# 3、XML解析优化

XML读取解析

public class XmlBeanDefinitionReader {

    SimpleBeanFactory simpleBeanFactory;

    /**
     * 构造函数
     */
    public XmlBeanDefinitionReader(SimpleBeanFactory simpleBeanFactory) {
        this.simpleBeanFactory = simpleBeanFactory;
    }

    /**
     * 遍历资源,将资源中的bean对象进行注册
     * @param resource 外部资源
     */
    public void loadBeanDefinitions(Resource resource) {
        while (resource.hasNext()) {
            Element element = (Element) resource.next();
            String beanID = element.attributeValue("id");
            String beanClassName = element.attributeValue("class");
            BeanDefinition beanDefinition = new BeanDefinition(beanID, beanClassName);
            simpleBeanFactory.registerBeanDefinition(beanDefinition);
        }
    }

}

XML上下文

public class ClassPathXmlApplicationContext implements BeanFactory {

    SimpleBeanFactory simpleBeanFactory;

    public ClassPathXmlApplicationContext(String fileName) {
        // 获取资源
        Resource resource = new ClassPathXmlResource(fileName);
        // 解析资源
        SimpleBeanFactory beanFactory = new SimpleBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(resource);
        this.simpleBeanFactory = beanFactory;
    }

    @Override
    public Object getBean(String beanName) throws BeansException {
        return simpleBeanFactory.getBean(beanName);
    }

    @Override
    public Boolean containsBean(String name) {
        return simpleBeanFactory.containsBean(name);
    }

    @Override
    public void registerBean(String beanName, Object obj) {
        simpleBeanFactory.registerBean(beanName, obj);
    }
}

上述两个类中使用的方法,都是simpleBeanFactory中的单例操作方法。

# 三、事件监听

构建好单例Bean的相关操作之后,为了监控容器的状态,方便后续使用观察者模式解耦代码提供入库,我们需要引入事件监听。

事件监听

public class ApplicationEvent extends EventObject {

    private static final long serialVersionUID = 1L;

    public ApplicationEvent(Object arg0) {
        super(arg0);
    }

}

事件发布

public interface ApplicationEventPublisher {
    void publishEvent(ApplicationEvent event);
}

# 四、扩展BeanDefinition

# 1、BeanDefinition扩展

之前我们所定义的BeanDefinition比较简单,只有两个属性:id和className,现对该类进行扩展如下:


public class BeanDefinition {
    /**
     * 单例
     */
    String SCOPE_SINGLETON = "singleton";

    /**
     * 原型
     */
    String SCOPE_PROTOTYPE = "prototype";

    /**
     * Bean id
     */
    private String id;

    /**
     * Bean类名
     */
    private String className;

    /**
     * Bean实例化类型(单例 | 原型)
     */
    private String scope = SCOPE_SINGLETON;

    /**
     * 是否在加载时候初始化
     */
    private boolean lazyInit = false;

    /**
     * 记录Bean之间依赖关系
     */
    private String[] dependsOn;

    /**
     * 初始方法声明
     */
    private String initMethodName;

    private volatile Object beanClass;
}

# 2、BeanDefinition操作

需要一个接口,来对BeanDefinition进行例如存放、移除、获取、判断是否存在等操作:

public interface BeanDefinitionRegistry {

    /**
     * 注册BeanDefinition
     * @param name 别名
     * @param beanDefinition BeanDefinition
     */
    void registerBeanDefinition(String name, BeanDefinition beanDefinition);

    /**
     * 删除BeanDefinition
     * @param name 别名
     */
    void removeBeanDefinition(String name);

    /**
     * 获取BeanDefinition
     * @param name 别名
     */
    BeanDefinition getBeanDefinition(String name);

    /**
     * 是否包含某个BeanDefinition
     * @param name 别名
     * @return
     */
    boolean containsBeanDefinition(String name);
}

# 3、BeanFactory新增接口

public interface BeanFactory {
    /**
     * 判断是否为单例
     * @param name 别名
     * @return
     */
    boolean isSingleton(String name);

    /**
     * 判断是否为原型
     * @param name 别名
     * @return
     */
    boolean isPrototype(String name);

    Class getType(String name);
}

新增三个方法:

  • 判断是否为单例
  • 判断是否为原型
  • 获取Bean的Class类

# 4、SimpleBeanFactory具体实现

SimpleBeanFactory类还需要额外实现BeanDefinition操作,以及BeanFactory新增的三个接口


public class SimpleBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory, BeanDefinitionRegistry{
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    private List<String> beanDefinitionNames = new ArrayList<>();

    public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
        this.beanDefinitionMap.put(name, beanDefinition);
        this.beanDefinitionNames.add(name);
        if (!beanDefinition.isLazyInit()) {
            try {
                getBean(name);
            } catch (BeansException e) {
            }
        }
    }
    public void removeBeanDefinition(String name) {
        this.beanDefinitionMap.remove(name);
        this.beanDefinitionNames.remove(name);
        this.removeSingleton(name);
    }
    public BeanDefinition getBeanDefinition(String name) {
        return this.beanDefinitionMap.get(name);
    }
    public boolean containsBeanDefinition(String name) {
        return this.beanDefinitionMap.containsKey(name);
    }
    public boolean isSingleton(String name) {
        return this.beanDefinitionMap.get(name).isSingleton();
    }
    public boolean isPrototype(String name) {
        return this.beanDefinitionMap.get(name).isPrototype();
    }
    public Class<?> getType(String name) {
        return this.beanDefinitionMap.get(name).getClass();
    }
}

# 参考

手把手带你写一个 MiniSpring (opens new window)

#Spring
上次更新: 2024/06/29, 15:13:44
Spring IoC-原始Ioc
Spring IoC-属性注入

← Spring IoC-原始Ioc Spring IoC-属性注入→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式