[Spring-1]Bean定义,注册,获取中体现的设计模式思考

[Spring-1]Bean定义,注册,获取中体现的设计模式思考

1.创建简单的Bean容器

a.BeanDefinition定义
 

typescript

代码解读

复制代码

public class BeanDefinition{    private Object bean;        public BeanDefinition(Object bean){        this.bean = bean;   }        public Object getBean(){        return bean;   }     }

b.关于BeanDefinition的工厂
 

typescript

代码解读

复制代码

public class BeanFactory{    private Map<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();        public Object getBean(String name){        return beanDefinitions.get(name).getBean();   }        public void registerBeanDefinition(String name,BeanDefinition beanDefinition){        beanDefinitionMap.put(name,beanDefinition);   } }

c.测试用例
 

java

代码解读

复制代码

public class Test{    @Test    public void test_BeanFactory(){        //1.初始化BeanFactory;        BeanFactory beanFactory = new BeanFactory();        //2.注册bean        BeanDefinition beanDefinition = new BeanDefinition(new UserService());        //3.获取bean        UserService userService = (UserService)beanFactory.getBean("userService");        userService.queryUserInfo();           } }

d.测试结果

 

vbnet

代码解读

复制代码

查询用户信息 ​ Process finished with exit code 0 ​

本案例中体现了:工厂模式

  • BeanDefinition是原材料

  • BeanDefinitionFactory提供一个Map作为容器

  • BeanDefinitionFactory提供getBean和registerBeanDefinition方法

    • 用getBean通过name拿到BeanDefinition
    • 用registerBeanDefinition将name和BeanDefinition的K-V组合注册到Map容器中

注明:

  • 本例中BeanDefinition存在Object类型的bean对象

    • 测试方法中:BeanDefinition beanDefinition = new BeanDefinition(new UserService()); 通过new了对象
    • 但在真实的Spring框架中,会用Class替代Object作为Bean
  • 替代的好处:

    a. 懒加载和延迟初始化

    使用类定义 bean 可以在需要时实例化对象,从而节省内存资源。这种懒加载机制可以提高应用的性能,尤其是当某些 bean 在应用启动时并不立即需要时。

    1. 单例模式

    Spring 默认使用单例模式来管理 bean。当使用类定义 bean 时,Spring 容器确保每个 bean 只有一个实例,这样可以避免不必要的对象创建和资源浪费,并提供全局共享的状态。

    1. 依赖注入

    通过类定义 bean,Spring 可以更容易地处理依赖注入。容器能够根据构造函数、字段或方法参数自动注入依赖项,提高了代码的解耦性和可测试性。

    1. 配置灵活性

    使用类描述 bean 使得通过 XML 或 Java 配置类灵活地配置 bean 的属性和依赖关系成为可能。这种灵活性允许开发者在不修改代码的情况下调整应用的行为。

    1. 生命周期管理

    Spring 能够更好地管理类定义的 bean 的生命周期,包括初始化、销毁等回调,这对于资源管理和清理至关重要。

    1. 类型安全

    通过类定义 bean,Spring 在编译时可以进行类型检查,减少了运行时错误的可能性。使用类时,IDE 提供的自动补全和提示功能也增强了开发体验。

    1. 支持 AOP

    使用类定义 bean 使得 Spring 能够应用面向切面编程(AOP),从而为 bean 提供横切关注点(如日志记录、事务管理等)的支持。

    1. 可扩展性

    使用类定义 bean,使得应用更易于扩展。如果需要添加新功能,只需创建新类或扩展现有类,而不必修改现有的实现。

2.实现 Bean 的定义、注册、获取

a.BeanDefinition的定义
 

kotlin

代码解读

复制代码

public class BeanDefinition { ​    private Class beanClass; ​    public BeanDefinition(Class beanClass) {        this.beanClass = beanClass;   } // ...get/set } ​

b.单例注册接口定义和实现

实际上:Spring支持Singleton Prototype Request Session Application Websocket六种bean的作用域

我们用到了:策略模式工厂模式

在 Spring 源码中,bean 的作用域注册器主要使用了策略模式(Strategy Pattern)和工厂模式(Factory Pattern)来实现。

1. 策略模式
  • 定义: 策略模式允许在运行时选择算法的行为。它通过定义一系列策略,并将每个策略封装起来,从而使得它们可以互换。

  • 应用

    : 在 Spring 中,针对不同的 bean 作用域(如 Singleton、Prototype 等),会定义不同的作用域策略接口和具体实现。每种作用域都有自己的实现类,例如:

    • SingletonScope
    • PrototypeScope
    • RequestScope
    • SessionScope

这些具体的作用域实现类都遵循相同的接口,使得容器能够根据 bean 的定义动态选择合适的作用域处理逻辑。

2. 工厂模式
  • 定义: 工厂模式提供了一个创建对象的接口,但让子类决定实例化哪一个类。

  • 应用

    : 在 Spring 中,

     

    sql

    代码解读

    复制代码

    Scope

    接口通常与

     

    代码解读

    复制代码

    BeanFactory

    结合使用。每个作用域都有自己的实例管理逻辑,通过工厂方法来创建和管理 bean 实例。例如:

    • DefaultSingletonBeanRegistry 管理 Singleton 范围的 bean
    • PrototypeBeanDefinition 会在每次请求时返回新的实例

这种设计使得 Spring 能够在不同作用域之间灵活切换,同时保持代码的高内聚性和低耦合性。

这里我们仅给出单例模式

 

arduino

代码解读

复制代码

public interface SingletonBeanRegistry{    Object getSingleton(String beanName);    /**    我认为此处需要做两个区分:    1.Singleton等多种策略,创建的是对象,是运行在Jvm中的实例    2.BeanFactory中创建的,是BeanDefinition,其中包含了beanClassName,    ProperityValues,    scope,    constructorArgumentValues,    autowireMode(自动装配的模式),    primary(该bean是否为首选的自动装配候选者),    factoryBeanName(倘若bean是用工厂方法创建的,得存一下工厂bean名称),    factoryMethodName( 如果使用工厂方法创建 bean,    这里存储工厂方法的名称。),    initMethodName(初始化方法名称),    destroyMethodName(指定销毁前执行的方法名称),    description(对bean的描述信息),    lazyInit(描述bean是否被懒加载),    role(bean在应用中的角色),    source(该bean的来源,是XML或者注释)        */ }

 

typescript

代码解读

复制代码

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistery{    private Map<String,Object> singletonObjects = new HashMap<>();    //1.此处用的是HashMap,而BeanDefinitions的Factory用的是ConcurrentHashMap    @Override    public Object getSingleton(String beanName) {        return singletonObjects.get(beanName);   } ​    protected void addSingleton(String beanName, Object singletonObject) {        singletonObjects.put(beanName, singletonObject);   } }

c.抽象类定义模版方法(AbstractBeanFactory)

注意:抽象类中的抽象方法(没有方法体的方法)在其子类中是必须被@Override的

 

scala

代码解读

复制代码

public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory { ​    @Override    public Object getBean(String name) throws BeansException {        Object bean = getSingleton(name);        if (bean != null) {            return bean;       } ​        BeanDefinition beanDefinition = getBeanDefinition(name);        return createBean(name, beanDefinition);   } ​    protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException; ​    protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException; ​ } ​

1.定义算法的框架

  • 固定流程getBean 方法定义了获取 bean 的基本流程,包括检查单例缓存、获取 bean 定义和创建 bean。这个方法提供了一个清晰的算法步骤。
  1. 延迟实现细节
  • 抽象方法getBeanDefinition 和 createBean 是抽象方法,它们的具体实现由子类提供。这允许子类根据不同的需求实现不同的逻辑,而不需要修改流程本身。
  1. 代码复用
  • 核心逻辑集中: 子类只需实现获取 bean 定义和创建 bean 的细节,而无需重复编写获取 bean 的核心逻辑。这种结构提升了代码的复用性,避免了冗余。
  1. 控制流程
  • 调用顺序: 在 getBean 方法中,控制了执行的顺序:先检查单例缓存,再获取 bean 定义,最后调用创建逻辑。这个顺序是固定的,确保了获取 bean 的一致性。
  1. 高内聚低耦合
  • 模块化设计AbstractBeanFactory 与其子类之间通过抽象方法进行交互,降低了耦合度。AbstractBeanFactory 只关心如何调用子类的实现,而不需要了解具体的创建逻辑。
  1. 易于扩展
  • 多种实现: 由于 getBeanDefinition 和 createBean 是抽象的,不同的子类可以实现不同的策略(例如,从 XML、注解或其他源加载 bean 定义),这为框架的扩展提供了极大的灵活性。
d.实例化Bean类(AbstractAutowireCapableBeanFactory)
  • 在 AbstractAutowireCapableBeanFactory 类中实现了 Bean 的实例化操作 newInstance,其实这块会埋下一个坑,有构造函数入参的对象怎么处理?可以提前思考
  • 在处理完 Bean 对象的实例化后,直接调用 addSingleton 方法存放到单例对象的缓存中去。
 

scala

代码解读

复制代码

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory { ​    @Override    protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {        Object bean = null;        try {            bean = beanDefinition.getBeanClass().newInstance();       } catch (InstantiationException | IllegalAccessException e) {            throw new BeansException("Instantiation of bean failed", e);       } ​        addSingleton(beanName, bean);        return bean;   } ​ }

  1. 工厂模式 (Factory Pattern)
  • 实例化对象createBean 方法负责创建 bean 实例,这符合工厂模式的核心理念,即将对象的创建逻辑封装在一个专门的类中。这使得 bean 的创建过程与其他业务逻辑分离,提供了清晰的构造方式。
  1. 单例模式 (Singleton Pattern)
  • 缓存管理: 在 createBean 中,创建的对象通过 addSingleton(beanName, bean) 被添加到单例缓存中。这种方式确保了对同一个 bean 名称的请求总是返回相同的实例,符合单例模式的行为。
  1. 模板方法模式 (Template Method Pattern)
  • 复用和扩展: 继承自 AbstractBeanFactory 的 AbstractAutowireCapableBeanFactory 利用模板方法 getBean 中定义的流程,同时实现了具体的 createBean 方法。这样可以复用获取 bean 的核心逻辑,而具体的 bean 创建逻辑则由子类定义。

4.为什么使用 protected 修饰符

  • 控制访问范围createBean 被声明为 protected,这意味着只有 AbstractAutowireCapableBeanFactory 的子类能够直接访问该方法。这种设计允许子类在不暴露实现细节的情况下重写或扩展 createBean 的行为。
  • 保护核心功能: 通过将 createBean 声明为 protected,可以防止外部代码直接调用这个方法,从而保护了 bean 创建的核心机制。这使得整个 bean 创建过程更加安全和可控。
  • 支持扩展性: 子类可以重写 createBean 方法,以添加自己的逻辑(例如,依赖注入、属性填充等),同时保持 AbstractBeanFactory 的核心流程。此外,确保了其他不相关的类不会干扰到 bean 的创建过程。
e.核心类实现(DefaultListableBeanFactory)
 

scala

代码解读

复制代码

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry { ​    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(); ​    @Override    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {        beanDefinitionMap.put(beanName, beanDefinition);   } ​    @Override    public BeanDefinition getBeanDefinition(String beanName) throws BeansException {        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);        if (beanDefinition == null) throw new BeansException("No bean named '" + beanName + "' is defined");        return beanDefinition;   } ​ } ​

  1. 工厂模式 (Factory Pattern)
  • 创建和管理 BeanDefaultListableBeanFactory 作为一个工厂类,负责注册和获取 bean 定义。通过 registerBeanDefinition 方法,可以将 bean 的定义信息存储在 beanDefinitionMap 中,而 getBeanDefinition 方法则提供了根据 bean 名称获取相应定义的功能。这种模式清晰地将 bean 的创建和管理逻辑封装在一个单独的类中,从而使得其他代码不必关心具体的实现细节。
  1. 策略模式 (Strategy Pattern)
  • 灵活的 Bean 管理DefaultListableBeanFactory 可以与不同的 bean 定义策略配合使用。例如,可以根据不同的需求提供不同类型的 bean 定义(如单例、原型等),而具体的创建逻辑则可以在 AbstractAutowireCapableBeanFactory 中实现。这种设计允许在运行时动态选择策略,使得 bean 的管理更加灵活。
  1. 模板方法模式 (Template Method Pattern)
  • 复用逻辑DefaultListableBeanFactory 可能会继承自 AbstractAutowireCapableBeanFactory,并利用其实现的一些通用逻辑,比如自动注入等。通过这种方式,它可以重写特定的方法以实现自己的逻辑,而无需重复实现所有的步骤。
  1. 适配器模式 (Adapter Pattern)
  • 接口适应: 作为 BeanDefinitionRegistry 接口的实现,DefaultListableBeanFactory 适应了 bean 定义的注册和获取功能。这种适配器设计使得这个工厂类可以被用作不同上下文中的 bean 管理器,而不需要改变原有的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值