1. 工厂模式
在 Spring Boot 中,工厂模式主要体现在 BeanFactory 和 ApplicationContext 接口的实现上。BeanFactory 是 Spring 中最基本的工厂模式实现,它负责创建和管理 Bean 对象。ApplicationContext 是 BeanFactory 的一个子接口,它增加了许多企业级的特性,如国际化、事件传递、AOP 等。ApplicationContext 的实现类包括 ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、AnnotationConfigApplicationContext 等。
我们通常使用注解(如 @Component、@Service、@Repository 等)来标记需要创建的对象,Spring 容器会根据这些注解来创建对象并管理它们的生命周期。具体实现可以参考 Spring Framework 的 BeanFactory 和 ApplicationContext 接口。
1.1 详解 DefaultListableBeanFactory
DefaultListableBeanFactory 是 Spring Framework 中的工厂模式的实现之一,它是 BeanFactory 接口的默认实现类。它负责创建和管理 Bean 对象,并提供了许多与 Bean 相关的操作,如 Bean 的注册、依赖注入、生命周期管理等。
DefaultListableBeanFactory 通过解析 XML 配置文件或者注解来创建 Bean 对象,并将其缓存在一个 Map 中,当需要获取 Bean 对象时,通过 getObjectForBeanInstance() 方法来获取对应 Bean 的实例对象。如果缓存中不存在该 Bean 的实例对象,则通过 createBean() 方法来创建一个新的实例对象并放入缓存中。
DefaultListableBeanFactory 是 Spring Framework 中的一个核心类,它实现了 BeanFactory 接口,并提供了创建、管理、销毁 Bean 对象的功能。下面我们来逐步解析 DefaultListableBeanFactory 的源码。
首先,我们来看一下 DefaultListableBeanFactory 的类定义:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { // ... }
可以看到,DefaultListableBeanFactory 继承了
AbstractAutowireCapableBeanFactory,并实现了
ConfigurableListableBeanFactory、BeanDefinitionRegistry 和 Serializable
接口。其中,AbstractAutowireCapableBeanFactory 提供了 Bean
自动装配的功能,ConfigurableListableBeanFactory 定义了可配置的 ListableBeanFactory
接口,BeanDefinitionRegistry 定义了 BeanDefinition 的注册接口,而 Serializable
则是为了支持对象序列化。
接下来,我们来看一下 DefaultListableBeanFactory 中的一些重要属性:
@Nullable private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); private final List<String> beanDefinitionNames = new ArrayList<>(256以上是 DefaultListableBeanFactory 中的一些重要属性,其中:
beanClassLoader:Bean 的类加载器,默认为 ClassUtils.getDefaultClassLoader(),即当前线程的上下文类加载器。
beanDefinitionMap:BeanDefinition 对象的缓存,key 为 Bean 的名称,value 为 BeanDefinition 对象。
beanDefinitionNames:Bean 的名称列表,用于快速遍历。
接下来我们来看一下 DefaultListableBeanFactory 中的一些重要方法:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) public void removeBeanDefinition(String beanName) public BeanDefinition getBeanDefinition(String beanName) public boolean containsBeanDefinition(String beanName) public String[] getBeanDefinitionNames() public int getBeanDefinitionCount() public boolean isBeanNameInUse(String beanName)
可以看到,这些方法主要用于 BeanDefinition 对象的注册、查询、删除和遍历操作。
接下来,我们来看一下 DefaultListableBeanFactory 中的一些重要方法:
public Object getBean(String name) public <T> T getBean(String name, Class<T> requiredType) public <T> T getBean(Class<T> requiredType) public Object getBean(String name, Object... args) public <T> T getBean(Class<T> requiredType,Object... args)
这些方法是 DefaultListableBeanFactory 中最核心的方法,它们用于获取 Bean 对象。其中,getBean() 方法是最常用的方法,它可以根据 Bean 的名称或类型来获取对应的 Bean 实例对象。具体来说,getBean()方法会先从缓存中查找对应的 Bean 实例对象,如果缓存中不存在,则通过 createBean() 方法来创建一个新的 Bean实例对象,并将其放入缓存中。
除了上述方法之外,DefaultListableBeanFactory 还提供了许多其他的方法和接口,用于处理 Bean 的生命周期、作用域、AOP 等方面的功能。例如,DefaultListableBeanFactory 中提供了以下方法:
public void destroySingletons() public void registerSingleton(String name, Object singletonObject) public Object getSingleton(String beanName) public boolean containsSingleton(String beanName) public int getSingletonCount()
这些方法主要用于管理单例对象的生命周期,包括单例对象的创建、销毁和缓存等操作。
最后,我们来看一下 DefaultListableBeanFactory 中 createBean() 方法的源码,该方法用于创建 Bean 实例对象。
protectedObject createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // Resolve before instantiating the bean to allow for short-circuits. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving很好,接下来我们继续解析 createBean() 方法的源码。 // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, exposedObject)); singletonObjects.remove(beanName); earlySingletonObjects.remove(beanName); registeredSingletons.add(beanName); } return exposedObject;
可以看到,createBean() 方法主要分为以下几个步骤:
创建 Bean 实例对象,并将其封装为 BeanWrapper 对象。如果 Bean 是单例对象,则从 factoryBeanInstanceCache 缓存中获取,否则通过 createBeanInstance() 方法来创建一个新的实例对象。
应用 MergedBeanDefinitionPostProcessor 对象到 Bean 上,以修改其 BeanDefinition 属性值和 Bean 实例对象。
初始化 Bean 实例对象,包括属性注入、初始化方法调用等操作。如果 Bean 是单例对象,则在初始化前进行缓存操作,以便后续解决循环依赖等问题。
如果 Bean 是单例对象,并且需要提前暴露,则将其缓存到 singletonFactories 中,并从 singletonObjects 和 earlySingletonObjects 缓存中移除。
返回 Bean 实例对象。
DefaultListableBeanFactory 的源码比较庞大,涉及的功能也比较复杂,需要结合具体的使用场景和实现细节来进行深入理解和分析。不过,通过对DefaultListableBeanFactory 的源码解析,我们可以更好地理解 Spring Framework 中的BeanFactory 设计模式,并从中获得一些启发和思考。
2. 单例模式
在 Spring Boot 中,单例模式主要体现在 Bean 的创建和管理上。默认情况下,Spring 容器会将 Bean 创建为单例对象,并在整个应用程序生命周期中保持唯一。这种单例模式的实现方式可以避免多线程竞争和资源浪费,同时也方便了对象的管理和维护。
在 Spring Boot 中,单例模式的实现可以参考 Spring Framework 的 DefaultSingletonBeanRegistry 接口。这个类维护了一个单例对象的缓存,通过 getObjectForBeanInstance() 方法来获取对应 Bean 的实例对象,如果缓存中不存在该 Bean 的实例对象,则通过 createBean() 方法来创建一个新的实例对象并放入缓存中。下面我们来逐步解析 DefaultListableBeanFactory 。
1.1 详解 DefaultSingletonBeanRegistry
首先,我们来看一下 DefaultSingletonBeanRegistry 中定义的方法:
public interface DefaultSingletonBeanRegistry { void registerSingleton(String beanName, Object singletonObject); Object getSingleton(String beanName); boolean containsSingleton(String beanName); String[] getSingletonNames(); int getSingletonCount(); }
可以看到,DefaultSingletonBeanRegistry 定义了单例 Bean 的注册、缓存和查询接口,包括 registerSingleton()、getSingleton()、containsSingleton()、getSingletonNames()和 getSingletonCount() 等方法。其中,registerSingleton() 方法用于将一个单例 Bean注册到缓存中,getSingleton() 方法用于获取指定名称的单例 Bean,containsSingleton()方法用于判断指定名称的单例 Bean 是否存在,getSingletonNames() 方法用于获取所有单例 Bean 的名称,getSingletonCount() 方法用于获取单例 Bean 的数量。
接下来我们看下 DefaultSingletonBeanRegistry 的实现,我给源码中添加一些注释方便大家理解
尤其大家可以看下spring 在单例实现中的线程安全是怎么做到额
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable, DefaultSingletonBeanRegistry { // ... private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 单例对象缓存 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 单例对象工厂缓存 private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); // 提前暴露的单例对象缓存 private final Set<String> registeredSingletons = new LinkedHashSet<>(256); // 已注册的单例对象集合 private final Set<String> disposableBeans = new LinkedHashSet<>(256); // 需要销毁的单例对象集合 // ... @Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { Assert.notNull(beanName, "Bean name must not be null"); // beanName 不能为空 synchronized (this.singletonObjects) { // 加锁,确保线程安全 Object oldObject = this.singletonObjects.get(beanName); // 查找缓存中是否已存在同名单例对象 if (oldObject != null) { throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"); // 如果已存在同名单例对象,则抛出异常 } this.singletonObjects.put(beanName, singletonObject); // 将单例对象放入缓存中 this.singletonFactories.remove(beanName); // 从单例对象工厂缓存中移除该对象 this.earlySingletonObjects.remove(beanName); // 从提前暴露的单例对象缓存中移除该对象 this.registeredSingletons.add(beanName); // 将该对象名称添加到已注册的单例对象集合中 } } @Override public Object getSingleton(String beanName) { return getSingleton(beanName, true); // 调用带有 allowEarlyReference 参数的 getSingleton() 方法 } protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); // 从缓存中获取指定名称的单例对象 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 如果缓存中不存在该单例对象,并且该对象正在创建过程中 synchronized (this.singletonObjects) { // 加锁,确保线程安全 singletonObject = this.earlySingletonObjects.get(beanName); // 从提前暴露的单例对象缓存中获取该对象 if (singletonObject == null && allowEarlyReference) { // 如果提前暴露的单例对象缓存中仍未找到该对象,并且允许提前暴露 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // 从单例对象工厂缓存中获取该对象的 ObjectFactory if (singletonFactory != null) { // 如果单例对象工厂存在 singletonObject = singletonFactory.getObject(); // 获取新的单例对象 this.earlySingletonObjects.put(beanName, singletonObject); // 将新的单例对象放入提前暴露的单例对象缓存中 this.singletonFactories.remove(beanName); // 从单例对象工厂缓存中移除该对象 } } } } return singletonObject; } @Override public boolean containsSingleton(String beanName) { return this.singletonObjects.containsKey(beanName); // 判断单例对象缓存中是否存在指定名称的单例对象 } @Override public String[] getSingletonNames() { synchronized (this.singletonObjects) { // 加锁,确保线程安全 return StringUtils.toStringArray(this.registeredSingletons); // 将已注册的单例对象集合转换为数组返回 } } @Override public int getSingletonCount() { synchronized (this.singletonObjects) { // 加锁,确保线程安全 return this.registeredSingletons.size(); // 返回已注册的单例对象集合的大小 } } // ... }
除了上述方法外,DefaultListableBeanFactory 还提供了一些其他方法来管理单例 Bean,例如 destroySingletons() 方法用于销毁所有的单例 Bean,getSingletonMutex() 方法用于获取单例对象的互斥锁等。
综上所述,DefaultSingletonBeanRegistry 接口及其默认实现类 DefaultListableBeanFactory 提供了一系列方法来管理单例对象的生命周期,包括注册、缓存、查询、销毁等操作,为 Spring Framework 的IoC 容器实现了核心的单例对象管理机制,确保了单例对象的唯一性和正确性。
3. 观察者模式
在 Spring Boot 中,观察者模式通常用于实现事件驱动的编程模型。Spring Framework 中的 ApplicationEvent 和 ApplicationListener 接口就是观察者模式的实现。ApplicationEvent 是事件对象的抽象类,它定义了事件发生时需要携带的数据。ApplicationListener 是事件监听器的接口,它定义了监听器需要实现的方法,当事件发生时,监听器会自动执行相应的处理逻辑。
在 Spring Boot 中,我们可以通过继承 ApplicationEvent 类来自定义事件对象,通过实现 ApplicationListener 接口来定义事件监听器。Spring 容器会自动扫描所有实现了 ApplicationListener 接口的 Bean,并将其注册为事件监听器。当事件发生时,Spring 容器会自动调用对应监听器的 onApplicationEvent() 方法来处理事件。
具体实现可以参考 Spring Framework 的 ApplicationEvent 和 ApplicationListener 接口,以及 AbstractApplicationContext、SimpleApplicationEventMulticaster 等类。
4. 适配器模式
在 Spring Boot 中,适配器模式通常用于将不兼容的接口转换成可兼容的接口。Spring Framework 中的适配器模式主要体现在以下两个方面:
控制器方法适配器:Spring MVC 中的控制器方法可以返回多种类型的结果,例如 ModelAndView、String、void 等,但是 Spring Boot 的 RESTful API 通常需要返回 JSON 或 XML格式的数据。为了将控制器方法的返回值转换成符合 RESTful API 要求的格式,Spring Boot 提供了多种适配器类,例如 MappingJackson2HttpMessageConverter、Jaxb2RootElementHttpMessageConverter 等。
具体实现可以参考 Spring Framework 的 HttpMessageConverter 接口及其实现类。
数据库驱动适配器:在 Spring Boot 中,JDBC 模板可以适配各种不同的数据库驱动,只需配置相应的数据源和驱动类即可。Spring Boot 中已经预置了许多常用的数据库驱动适配器,包括 H2、MySQL、PostgreSQL、Oracle 等。
具体实现可以参考 Spring Framework 的 JdbcTemplate 和 DataSource 接口及其实现类,以及 DriverManagerDataSource、HikariDataSource 等数据源实现类。
5. 模板方法模式
在 Spring Boot 中,模板方法模式通常用于实现通用的业务逻辑。Spring Framework 中的 JdbcTemplate 和 HibernateTemplate 就是模板方法模式的实现。这些模板类定义了通用的数据访问操作,如查询、插入、更新、删除等,而具体的数据访问细节则由子类(如 JdbcDaoSupport、HibernateDaoSupport 等)来实现。
我们可以使用 JdbcTemplate 来执行 SQL 操作,它封装了 JDBC
的基本操作,如打开和关闭连接、创建和执行语句等。我们可以通过定义 RowMapper 接口来映射查询结果集到对象上,JdbcTemplate
会自动将查询结果集转换成对象列表。具体实现可以参考 Spring Framework 的 JdbcTemplate 和 RowMapper
接口及其实现类,以及 NamedParameterJdbcTemplate、SimpleJdbcInsert 等模板类。
好了,我是冰点,今天的分享就到这儿,下次见,如果对你有帮助点赞收藏,如果有疑问可以在评论区留言。