Spring中所使用的设计模式

本文深入探讨了Spring框架中使用的设计模式,包括工厂模式(BeanFactory和ApplicationContext)、单例模式、策略模式(如Resource的实现)、代理模式(AOP中的JDK和CGLIB)、模板方法(如RestTemplate)、适配器模式(Advice转换)和观察者模式(事件驱动)。Spring通过这些模式实现了对象创建、依赖注入、功能扩展和事件处理等功能。
摘要由CSDN通过智能技术生成

Spring是一个非常优秀的开源框架,项目源码中所使用的设计模式随处可见,这篇文章主要记录一下Spring中常见的设计模式:

(1)工厂模式:Spring使用工厂模式,通过BeanFactory和ApplicationContext来创建对象

(2)单例模式:Bean默认为单例模式

(3)策略模式:例如Resource的实现类,针对不同的资源文件,实现了不同方式的资源获取策略

(4)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术

(5)模板方法:可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中,用来解决代码重复的问题。比如RestTemplate, JmsTemplate, JpaTemplate

(6)适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式,Spring MVC中也是用到了适配器模式适配Controller

(7)观察者模式:Spring事件驱动模型就是观察者模式的一个经典应用。

(8)桥接模式:可以根据客户的需求能够动态切换不同的数据源。比如我们的项目需要连接多个数据库,客户在每次访问中根据需要会去访问不同的数据库

一、工厂模式:
对于工厂模式不了解地读者可以阅读另外一篇文章:Java设计模式之创建型模式:工厂模式(简单工厂模式+工厂方法模式)

工厂模式是把创建对象的任务交给工厂,从而来降低类与类之间的耦合。Spring最主要的两个特性就是AOP和IOC,其中IOC就是控制反转,将对象的控制权转移给Spring,并由Spring创建实例和管理各个实例之间的依赖关系,其中,对象的创建就是通过BeanFactory 和 ApplicationContext 完成的。

1、首先看BeanFatory的源码:

public interface BeanFactory {
    Object getBean(String name) throws BeansException;
    
    <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
    
    Object getBean(String name, Object... args) throws BeansException;
    
    <T> T getBean(Class<T> requiredType) throws BeansException;
    
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    //省略...
}

BeanFactory是Spring里面最底层的接口,是IoC的核心,定义了IoC的基本功能,包含了各种Bean的定义、加载、实例化,依赖注入和生命周期管理。BeanFactroy采用的是延迟加载形式来注入Bean的,只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能提前发现一些存在的Spring的配置问题。

2、ApplicationContext接口作为BeanFactory的子类,除了提供BeanFactory所具有的功能外,还扩展了其他更完整功能,对于Bean创建,ApplicationContext在容器启动时,一次性创建了所有的Bean。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    @Nullable
    String getId();
 
    String getApplicationName();
 
    String getDisplayName();
 
    long getStartupDate();
 
    @Nullable
    ApplicationContext getParent();
 
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

3、BeanFactory 和 ApplicationContext 在哪里初始化Bean就不展开细讲,主要看AbstractApplicationContext类的refresh()方法。

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //省略...
        try {
            //省略...
            //初始化所有的单实例 Bean(没有配置赖加载的)
            finishBeanFactoryInitialization(beanFactory);
        }catch (BeansException ex) {
            //省略...
        }finally {
            //省略...
        }
    }
}

二、单例模式:
对于单例模式不了解地读者可以阅读另外一篇文章:Java设计模式之创建型模式:单例模式

在Spring中的Bean默认的作用域就是singleton单例的。单例模式的好处在于对一些重量级的对象,省略了重复创建对象花费的时间,减少了系统的开销,第二点是使用单例可以减少new操作的次数,减少了GC线程回收内存的压力。

对于单例bean的创建方式,主要看DefaultSingletonBeanRegistry 的 getSingleton() 方法:
 

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    /** 保存单例Objects的缓存集合ConcurrentHashMap,key:beanName --> value:bean实例 */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
 
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized (this.singletonObjects) {
            //检查缓存中是否有实例,如果缓存中有实例,直接返回
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                //省略...
                try {
                    //通过singletonFactory获取单例
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                //省略...
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            //返回实例
            return singletonObject;
        }
    }
    
    protected void addSingleton(String beanName, Object singletonObject) {
      synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, singletonObject);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
      }
    }
}

从源码中可以看出,是通过ConcurrentHashMap的方式,如果在Map中存在则直接返回,如果不存在则创建,并且put进Map集合中,并且整段逻辑是使用同步代码块包住的,所以是线程安全的。

三、策略模式:
对于策略模式不了解地读者可以阅读另外一篇文章:Java设计模式之行为型模式:策略模式

策略模式,简单来说就是封装好一组策略算法,外部客户端根据不同的条件选择不同的策略算法解决问题。比如在Spring的Resource类,针对不同的资源,Spring定义了不同的Resource类的实现类,以此实现不同的访问方式。我们看一张类图:

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青藤伽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值