spring常用的设计模式
一、单例模式
首先要说的便是单例模式,单例模式大家都知道目的是为了确保一个类只有一个实例,在spring中,我们就拿最典型的三级缓存来说明吧。
我们看下spring中DefaultSingletonBeanRegistry类中的getSingleton方法的源码,如下所示,相信看了代码中的详细说明可以很清楚的知道单例模式在spring中用三级缓存解决循环依赖的用处了。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
//singletonObjects这个是第一级缓存,这个缓存里面存放的是已经准备就绪的bean
//先根据beanName从第一级缓存中找,如果找到直接返回第一级缓存中缓存的bean。
Object singletonObject = this.singletonObjects.get(beanName);
//如果第一级缓存中没有找到对应的实例,并且发现这个bean目前正在创建中,还没有创建完成
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//这里就从第二级缓存中尝试获取,第二级缓存缓存的是半成品bean(实例化已完成但还未完成
//初始化),如果第二级缓存中有这个bean,那么就直接返回半成品bean
singletonObject = this.earlySingletonObjects.get(beanName);
//如果第二级缓存里面也没有这个bean,并且允许早期引用(主要是为了解决循环依赖)
if (singletonObject == null && allowEarlyReference) {
//前两级缓存都没有,就要使用第三级缓存了,但使用前要先加锁,对第一级缓存加锁
synchronized(this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
//加锁成功后,为了避免重复创建对象,再次尝试从第一级缓存获取,有就直接返回
singletonObject = this.singletonObjects.get(beanName);
//如果第一级缓存中依然没有这个bean
if (singletonObject == null) {
//那么就接着从第二级缓存中尝试获取,有就直接返回
singletonObject = this.earlySingletonObjects.get(beanName);
//如果发现第二级缓存中还没有
if (singletonObject == null) {
//接着就从第三级缓存中获取到由创建bean所需元素组成的ObjectFactory
//(这是一个lambda表达式)
ObjectFactory <? > singletonFactory = this.singletonFactories.get(beanName);
//如果第三级缓存中找到了这个bean进行实例化的信息
if (singletonFactory != null) {
//执行第三级缓存中的lambda表达式,从而创建bean实例
singletonObject = singletonFactory.getObject();
//将新创建的实例放入第二级缓存中(第二级缓存存的就是实例化完,
//但还未初始化的半成品)
this.earlySingletonObjects.put(beanName, singletonObject);
//放入第二级缓存的同时,从第三级缓存中删掉该bean,这么做也是为
//了避免重复创建bean的实例。也就是说第二级缓存和第三级缓存是
//互斥的,而且都是在加锁的场景下操作的,这也就是为啥第一级缓存
//用的是concurrenthashmap,而第二、第三级缓存用的是普通
//的hashmap,因为人家都前提加锁了,再用线程安全的map也没啥意义。
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
二、工厂模式
先来简单说下什么是工厂模式,工厂模式是将对象的创建交由统一的工厂类来生成对象,避免直接在代码中硬编码具体类的实例化过程。它适用于需要灵活管理对象创建的场景,例如根据条件动态创建不同类型对象,隐藏对象创建的复杂性等。
那么在spring中,工厂模式最典型的当然要数自动创建bean对象了,我们在类上加上@Component注解或@Resource等注解,spring就会帮我们去自动创建bean对象,不需要我们再手动专门new一个对象出来,下面我举spring中创建bean对象的一个关键方法来说明
我们先来看下AbstractBeanFactory工厂类,也叫抽象工厂类,这个工厂类只提供了一个抽象方法,createBean,具体创建bean的过程由对应的子类来实现。
/**
* Create a bean instance for the given merged bean definition (and arguments).
* The bean definition will already have been merged with the parent definition
* in case of a child definition.
* <p>All bean retrieval methods delegate to this method for actual bean creation.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
*/
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException;
AbstractAutowireCapableBeanFactory是AbstractBeanFactory的子类,这个从名字上就可以知道它也是一个工厂类,是管理spring bean生命周期的核心实现类,属于IoC容器的底层基础设施。它直接负责Bean的实例化、属性填充(依赖注入)、初始化方法调用等关键操作,是Spring实现依赖注入(DI)和自动装配(Autowiring)的核心引擎,如下图所示。
这个类就实现了父类createBean的方法,如下所示,我们不做深入研究源码,而是重点看工厂模式的运用,这个方法最下面的那个try代码块中有一行是Object beanInstance = doCreateBean(beanName, mbdToUse, args);这是真正去创建bean对象的方法。
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class <? > resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
doCreateBean方法源码如下,下面实例化、属性填充、初始化的地方我都用中文加了注释,也就是执行完这个方法后,我们写在项目里的实体类就被spring自动给创建好了,这省去了我们非常多的麻烦,让我们可以专心关注具体业务,而不用操心繁杂的bean创建过程。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//这行代码是去创建bean的实例(但还未填充属性也未初始化)
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
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) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
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.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () - > getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//这行代码是要填充bean属性(也就是依赖注入)
populateBean(beanName, mbd, instanceWrapper);
//这行代码是要对bean进行初始化,这里面包括初始化前Aware接口回调,初始化前置处理、初始化、初始化后置处理等动作
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) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set < String > actualDependentBeans = new LinkedHashSet < > (dependentBeans.length);
for (String dependentBean: dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
三、代理模式
首先说下什么是代理模式,它是通过创建一个代理对象来控制对原始对象(目标对象)的访问。代理对象在客户端和目标对象之间充当中介,可以在不修改目标对象代码的前提下,增强其功能(如添加日志、权限控制、加缓存等)。
在spring中用到的代理分为两类,一类是JDK动态代理,这种针对的是是接口,如果目标对象实现了接口,那么就使用JDK动态代理。另一类是CGLIB代理,这种是目标对象没有实现接口。
我们举个例子就比较清楚了,像下面这样,UserServiceImpl实现了UserService的接口,那么这种场景,spring就使用JDK动态代理来生成代理对象。
public interface UserService {
void saveUser(User user);
}
@Service
public class UserServiceImpl implements UserService {
@Override
public void saveUser(User user) {
// 数据库操作
}
}
而比如像我们下面的这个Student类,它只是加了@Component注解,而没有实现具体的接口,因此这个类在spring中就以CGLIB的代理模式创建代理对象。
package com.example.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Student {
@Autowired
private Cource cource;
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
四、策略模式
首先说下什么是策略模式,策略模式是一种行为型设计模式,它定义了一系列算法(策略),并将每个算法封装成独立的类,使得它们可以相互替换。策略模式的核心思想是将算法的使用和算法的实现解耦,客户端可以根据需求动态选择不同的策略,而无需修改原有代码。
那么在spring中哪些场景用到了策略模式呢?下面我们举两个最常用的例子
第一个:创建代理对象
策略接口:AopProxy
具体策略:
JdkDynamicAopProxy:基于JDK动态代理生成接口代理。
CglibAopProxy:基于CGLIB生成子类代理。
第二个例子:资源加载(ResourceLoader)
策略接口:ResourceLoader
具体策略:
ClassPathResource:加载类路径资源。
FileSystemResource:加载文件系统资源。
UrlResource:加载网络资源(URL)
应用场景:根据资源路径前缀(如classpath:、file:)选择资源加载策略。
五、观察者模式
首先说下什么是观察者模式,观察者模式是一种行为型设计模式,用于定义对象间的一对多依赖关系。当一个对象(称为主题或被观察者)的状态发生改变时,所有依赖它的对象(称为观察者)都会自动收到通知并更新自身状态。该模式的核心思想是解耦主题与观察者,使它们可以独立变化和扩展。
观察者模式在spring中的应用,举个例子:bean的初始化与销毁回调
场景描述:Bean的初始化(如@PostConstruct)和销毁(如@PreDestry)通过事件机制触发,监听器执行回调逻辑。
源码实现:
事件类型:BeanInitializationEvent
、BeanDestructionEvent
(内部事件,非直接暴露)。
处理逻辑:InitDestroyAnnotationBeanPostProcessor
监听 Bean 的创建过程,解析 @PostConstruct
和 @PreDestroy
注解。
六、模板模式
模板模式是一种行为型设计模式,用于定义一个操作中算法的骨架,将某些步骤的具体实现延迟到子类中去完成。它允许子类在不改变算法结构的情况下,重新定义某些步骤的实现。
在spring中,使用模板模式的例子,像下面这个类,commit方法定义了事务的提交流程,提供了一个抽象方法doCommit(),交由实现具体的事务提交逻辑。
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager {
@Override
public final void commit(TransactionStatus status) {
// 固定流程:检查状态 → 处理回滚 → 触发同步 → 提交
if (status.isCompleted()) {
throw new IllegalTransactionStateException("事务已提交或回滚");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
processRollback(defStatus, false);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
processRollback(defStatus, true);
return;
}
processCommit(defStatus); // 调用具体提交逻辑
}
// 抽象方法,由子类实现
protected abstract void doCommit(DefaultTransactionStatus status);
}
子类DataSourceTransactionManager为例,实现了doCommit方法,同时又可以利用父类的commit公共方法,这种就是模板模式的应用。
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager {
@Override
protected void doCommit(DefaultTransactionStatus status) {
Connection con = status.getTransaction().getConnectionHolder().getConnection();
try {
con.commit(); // 实际提交事务(JDBC 实现)
} catch (SQLException ex) {
throw new TransactionSystemException("提交失败", ex);
}
}
}