前言
Spring 是 Java 领域中最流行的应用程序开发框架之一,它为 Java 程序员们提供了很多强大的功能和工具,以帮助开发出更高效、更健壮、更可维护的应用系统。在 Spring 的源码实现过程中,借鉴和运用了许多经典的设计模式,这些模式可以帮助我们更好地理解 Spring 的设计和实现思路。本文将介绍 Spring 框架内部使用的一些重要的设计模式,以及它们的应用和好处。
工厂模式
工厂模式是一种常用的创建型设计模式,它将对象的创建过程封装在一个单独的类(即工厂类)中,并由工厂类来负责生成需要的对象。这种方式可以有效地避免创建对象时的重复代码,同时也可以更好地控制对象的创建过程。在 Spring 框架中,BeanFactory 就是一个典型的工厂类,它负责创建和管理应用中所有的 Bean 实例。
BeanFactory 接口定义了一系列方法,用于获取、创建和销毁 Bean 实例。其中,getBean(String name) 方法就是一个典型的工厂方法,它接受一个字符串类型的参数 name,表示要获取的 Bean 实例的名称,然后通过配置文件或注解等方式来确定具体的 Bean 实现类,最终返回对应的 Bean 实例。使用工厂模式可以帮助我们更好地组织和管理应用中的对象,提高代码的重用性和可维护性。
源码解析
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected T doGetBean(final String name, final Class requiredType, final Object[] args,
boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 1. 尝试从 singleton 缓存中获取指定名称的 singleton 实例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 2. 处理单例缓存中不存在指定名称的 singleton 实例的情况
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 3. 将当前 beanName 标记为正在创建中
beforeSingletonCreation(beanName);
try {
// 4. 获取指定名称的 BeanDefinition 对象,如果不存在则抛出 NoSuchBeanDefinitionException 异常
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 5. 进行 factory-bean 的处理和初始化方法的合并
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 6. 在缓存中删除当前 beanName 对应的 singleton 实例,以确保每次都能够重新创建实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 7. 创建失败时需要在缓存中清除当前缓存的 singleton 实例
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 8. 处理 prototype 类型的 Bean 实例
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 9. 创建失败时需要在删除当前 scope 中缓存的实例
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
destroyScopedBean(beanName);
}
throw ex;
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
finally {
// 10. 创建 Bean 实例完成后取消当前 beanName 的创建标记
afterSingletonCreation(beanName);
}
}
// 11. 兼容性处理
if (requiredType != null && !requiredType.isInstance(bean)) {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
return (T) bean;
}
代理模式
代理模式是一种常用的结构型设计模式,它允许一个对象(即代理类)作为另一个对象(即被代理对象)的替身,以控制对被代理对象的访问。在 Spring 框架中,AOP(面向切面编程)就是典型的代理模式的应用。通过使用 AOP,Spring 能够在运行时将某些通用的行为(例如事务、日志记录等)动态地织入到应用程序中的某个切面里,从而实现更好的解耦合和可维护性。
Spring 框架中使用了两种代理模式:JDK 动态代理和 CGLIB 代理。JDK 动态代理是基于 Java 反射机制实现的,它只能代理接口的实现类,不支持非接口的类。而 CGLIB 代理是基于字节码生成技术实现的,它可以代理任意的类,但需要依赖于字节码生成技术,所以效率上不如 JDK 动态代理。
单例模式
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。在 Spring 框架中,单例模式扮演了非常重要的角色,它是 Spring 容器中 Bean 的默认作用域,确保了应用中某些关键对象的唯一性和全局可见性。
Spring 框架通过一个叫做 SingletonBeanRegistry 的接口来实现单例模式的管理。这个接口定义了一系列方法,如 registerSingleton()、getSingleton() 和 containsSingleton() 等,用于注册、获取和判断单例实例。Spring 容器在初始化时会自动创建并缓存所有的单例 Bean 实例,之后所有的 getBean() 请求都会从缓存中获取实例,以确保每个对象的唯一性和全局可见性。
观察者模式
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,即当一个对象的状态发生改变时,所有的依赖对象都会收到通知并自动更新。在 Spring 框架中,事件驱动模型就是典型的观察者模式的应用。通过使用事件驱动模型,Spring 能够实现对象之间的松耦合和模块化设计。
Spring 框架中的事件驱动模型由 ApplicationEvent 和 ApplicationListener 两个接口组成,其中 ApplicationEvent 定义了应用程序中所有事件的基类,而 ApplicationListener 则定义了所有事件监听器的基本方法。使用观察者模式可以将各个模块或组件之间的依赖关系降至最低,从而提高了应用的灵活性和可维护性。
总结
Spring 框架是一个非常重要的 Java 应用程序开发框架,它运用了许多经典的设计模式来实现各种功能和工具。在本文中,我们介绍了 Spring 中使用的一些重要的设计模式,包括工厂模式、代理模式、单例模式和观察者模式。这些模式不仅能够帮助我们更好地理解 Spring 的设计和实现思路,还能够提高代码的复用性、可维护性和扩展性。