专业的JAVA编程教程与资源

网站首页 > java教程 正文

深入理解 Spring 设计模式:从实现原理到思想精髓

temp10 2025-08-05 21:13:25 java教程 2 ℃ 0 评论

设计模式是框架设计的 “灵魂”,Spring 作为 Java 生态中最成功的框架之一,其优雅性很大程度上源于对设计模式的灵活运用。在手写 mini-spring 框架的过程中,深入理解这些模式的应用场景和解决思路,不仅能帮助我们看懂框架源码,更能提升自己的架构设计能力。本文将结合实战案例,详解 Spring 中核心设计模式的实现与价值。

一、创建型模式:控制对象的创建逻辑

创建型模式专注于 “如何创建对象”,Spring 通过这些模式将对象的创建与使用解耦,这也是 IoC 容器的核心思想。

深入理解 Spring 设计模式:从实现原理到思想精髓

1. 工厂模式:IoC 容器的 “心脏”

核心问题:如何统一管理对象的创建过程,避免硬编码依赖?

Spring 中的实现
Spring 的 IoC 容器本质是一个超级工厂
DefaultListableBeanFactory作为核心工厂类,负责所有 Bean 的创建、管理和销毁。

// 简化的BeanFactory接口(工厂接口)
public interface BeanFactory {
    // 核心方法:获取Bean(生产对象)
    Object getBean(String name) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
}

// 核心实现类:DefaultListableBeanFactory
public class DefaultListableBeanFactory implements BeanFactory, BeanDefinitionRegistry {
    // 存储Bean定义(相当于“产品图纸”)
    private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    
    // 存储已创建的Bean(相当于“产品实例”)
    private final Map<String, Object> singletonObjects = new HashMap<>();
    
    @Override
    public Object getBean(String name) {
        // 1. 检查缓存中是否已有实例(单例)
        Object bean = singletonObjects.get(name);
        if (bean != null) {
            return bean;
        }
        
        // 2. 从BeanDefinition中获取“创建图纸”
        BeanDefinition beanDefinition = beanDefinitionMap.get(name);
        if (beanDefinition == null) {
            throw new NoSuchBeanDefinitionException(name);
        }
        
        // 3. 根据BeanDefinition创建Bean(核心逻辑)
        bean = createBean(beanDefinition);
        
        // 4. 缓存单例Bean
        if (beanDefinition.isSingleton()) {
            singletonObjects.put(name, bean);
        }
        return bean;
    }
    
    // 创建Bean的具体实现(模板方法,由子类扩展)
    protected Object createBean(BeanDefinition beanDefinition) {
        try {
            // 简化版:直接通过反射创建实例(实际包含依赖注入、初始化等步骤)
            Class<?> beanClass = beanDefinition.getBeanClass();
            return beanClass.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new BeansException("Failed to create bean", e);
        }
    }
}

设计价值

  • 开发者无需手动new对象,只需通过getBean从工厂获取,实现了 “控制反转”;
  • 工厂统一管理 Bean 的创建逻辑(如依赖注入、初始化),将复杂创建过程封装,简化上层使用;
  • 扩展性强:通过实现BeanFactory接口,可自定义工厂逻辑(如XmlBeanFactory从 XML 加载 Bean 定义)。

2. 单例模式:Bean 实例的 “唯一性” 保障

核心问题:如何确保某个对象在容器中只有一个实例,避免重复创建消耗资源?

Spring 中的实现
Spring 的singleton作用域默认使用单例模式,但并非简单的 “饿汉 / 懒汉式”,而是由BeanFactory统一管理单例的生命周期:

public class DefaultListableBeanFactory {
    // 单例Bean缓存池:key=beanName,value=单例实例
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    // 正在创建中的单例Bean(解决循环依赖)
    private final Map<String, Object> singletonFactories = new HashMap<>(16);
    
    // 获取单例Bean的核心逻辑
    protected Object getSingleton(String beanName) {
        // 1. 先从缓存中取
        Object singletonObject = singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 2. 标记为“正在创建”(避免并发创建)
            synchronized (this.singletonObjects) {
                singletonObject = singletonObjects.get(beanName);
                if (singletonObject == null) {
                    // 3. 调用创建逻辑(由子类实现)
                    singletonObject = createBean(beanName);
                    // 4. 放入缓存,标记为“已创建”
                    singletonObjects.put(beanName, singletonObject);
                }
            }
        }
        return singletonObject;
    }
}

与传统单例的区别

  • 传统单例模式将实例控制逻辑硬编码在类内部(如私有构造器),而 Spring 将单例管理交给容器,类本身无需关心单例实现;
  • 支持 “延迟初始化”(默认)和 “提前初始化”(lazy-init=false),灵活度更高;
  • 结合singletonFactories解决了循环依赖问题(如 A 依赖 B,B 依赖 A 时,通过工厂提前暴露半成品实例)。

3. 建造者模式:复杂对象的 “分步构建”

核心问题:如何简化复杂对象的创建过程(如包含多个属性、嵌套结构的对象)?

Spring 中的实现
BeanDefinitionBuilder用于构建BeanDefinition(Bean 的元数据),BeanDefinition包含类名、作用域、依赖等多个属性,建造者模式让构建过程更清晰:

// 复杂对象:BeanDefinition
public class BeanDefinition {
    private Class<?> beanClass;
    private String scope = "singleton";
    private boolean lazyInit = false;
    private ConstructorArgumentValues constructorArgumentValues; // 构造器参数
    private MutablePropertyValues propertyValues; // 属性值
    // 省略getter/setter
}

// 建造者类:BeanDefinitionBuilder
public class BeanDefinitionBuilder {
    // 持有目标对象
    private final BeanDefinition beanDefinition;
    
    // 私有构造器,通过静态方法创建建造者
    private BeanDefinitionBuilder(Class<?> beanClass) {
        this.beanDefinition = new BeanDefinition();
        this.beanDefinition.setBeanClass(beanClass);
    }
    
    // 静态工厂方法:创建建造者
    public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) {
        return new BeanDefinitionBuilder(beanClass);
    }
    
    // 分步设置属性
    public BeanDefinitionBuilder setScope(String scope) {
        this.beanDefinition.setScope(scope);
        return this; // 链式调用
    }
    
    public BeanDefinitionBuilder setLazyInit(boolean lazyInit) {
        this.beanDefinition.setLazyInit(lazyInit);
        return this;
    }
    
    public BeanDefinitionBuilder addPropertyValue(String name, Object value) {
        this.beanDefinition.getPropertyValues().add(name, value);
        return this;
    }
    
    // 构建最终对象
    public BeanDefinition getBeanDefinition() {
        return this.beanDefinition;
    }
}

// 使用示例
public class BuilderTest {
    public static void main(String[] args) {
        // 链式调用构建复杂的BeanDefinition
        BeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(UserService.class)
                .setScope("prototype")
                .setLazyInit(true)
                .addPropertyValue("userDao", new RefBeanDefinition("userDao"))
                .getBeanDefinition();
    }
}

设计价值

  • 将复杂对象的构建步骤拆分,通过链式调用简化代码,提高可读性;
  • 隐藏BeanDefinition的内部结构,避免直接操作其属性导致的错误;
  • 便于扩展:如需新增属性,只需在建造者中添加对应方法,无需修改使用方。

二、结构型模式:优化对象的组合与交互

结构型模式关注 “对象如何组合”,Spring 通过这些模式实现了功能的灵活扩展和模块解耦。

1. 代理模式:AOP 的 “灵魂实现”

核心问题:如何在不修改原有代码的情况下,为方法添加额外功能(如日志、事务)?

Spring 中的实现
AOP(面向切面编程)通过代理模式实现,Spring 支持 JDK 动态代理(基于接口)和 CGLIB 代理(基于类):

// 目标接口
public interface UserService {
    void save();
}

// 目标实现类
public class UserServiceImpl implements UserService {
    @Override
    public void save() {
        System.out.println("执行save方法");
    }
}

// 切面逻辑:方法执行前后打印日志
public class LogAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 前置增强
        System.out.println("方法执行前:" + invocation.getMethod().getName());
        // 执行目标方法
        Object result = invocation.proceed();
        // 后置增强
        System.out.println("方法执行后:" + invocation.getMethod().getName());
        return result;
    }
}

// 代理工厂:创建代理对象
public class ProxyFactory {
    public static Object createProxy(Object target, MethodInterceptor advice) {
        // JDK动态代理(仅支持接口)
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            (proxy, method, args) -> {
                // 调用切面逻辑
                return advice.invoke(new ReflectiveMethodInvocation(target, method, args));
            }
        );
    }
    
    // 测试
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        // 创建代理对象(织入切面)
        UserService proxy = (UserService) ProxyFactory.createProxy(target, new LogAdvice());
        // 调用代理对象的方法
        proxy.save();
    }
}

设计价值

  • 实现了 “横切逻辑”(如日志、事务)与 “业务逻辑” 的解耦,无需修改业务代码;
  • 支持动态扩展:通过添加新的切面,可在不影响原有功能的情况下新增功能;
  • 灵活性高:可根据目标对象是否有接口自动选择 JDK 或 CGLIB 代理。

2. 适配器模式:接口适配的 “万能转换头”

核心问题:如何让接口不兼容的类能够一起工作?

Spring 中的实现
Spring MVC 的HandlerAdapter是适配器模式的典型应用。MVC 中存在多种处理器(Controller),如@RequestMapping注解的控制器、HttpRequestHandler等,HandlerAdapter适配不同处理器,让DispatcherServlet无需关心具体类型:

// 适配器接口
public interface HandlerAdapter {
    // 判断是否支持当前处理器
    boolean supports(Object handler);
    // 执行处理器逻辑
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

// 适配@RequestMapping注解的控制器
public class RequestMappingHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        // 支持带@RequestMapping的控制器
        return handler instanceof HandlerMethod && hasRequestMappingAnnotation((HandlerMethod) handler);
    }
    
    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 调用注解控制器的方法(简化逻辑)
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Object result = handlerMethod.invoke();
        return new ModelAndView(result.toString());
    }
}

// 适配HttpRequestHandler
public class HttpRequestHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return handler instanceof HttpRequestHandler;
    }
    
    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        ((HttpRequestHandler) handler).handleRequest(request, response);
        return null; // 无视图返回
    }
}

// DispatcherServlet中使用适配器
public class DispatcherServlet {
    private List<HandlerAdapter> handlerAdapters;
    
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 1. 找到对应的处理器(如Controller)
        Object handler = getHandler(request);
        // 2. 找到支持该处理器的适配器
        HandlerAdapter adapter = getHandlerAdapter(handler);
        // 3. 通过适配器执行处理器逻辑
        ModelAndView mv = adapter.handle(request, response, handler);
        // 渲染视图...
    }
}

设计价值

  • 隔离了DispatcherServlet与具体处理器的耦合,DispatcherServlet只需调用适配器的handle方法,无需关心处理器类型;
  • 便于扩展:新增处理器类型时,只需添加对应的适配器,无需修改DispatcherServlet源码(符合开闭原则)。

3. 装饰器模式:功能增强的 “灵活包装”

核心问题:如何在不修改原有对象的情况下,动态增强其功能?

Spring 中的实现
HttpServletRequestWrapper和
HttpServletResponseWrapper通过装饰器模式增强请求和响应对象:

// 原始接口
public interface HttpServletRequest {
    String getParameter(String name);
    // 其他方法...
}

// 装饰器类(实现相同接口,持有原始对象)
public class HttpServletRequestWrapper implements HttpServletRequest {
    private final HttpServletRequest request;
    
    public HttpServletRequestWrapper(HttpServletRequest request) {
        this.request = request;
    }
    
    // 默认调用原始对象的方法
    @Override
    public String getParameter(String name) {
        return request.getParameter(name);
    }
    
    // 可重写方法实现增强
    public String getParameterWithTrim(String name) {
        String value = request.getParameter(name);
        return value != null ? value.trim() : null;
    }
}

// 使用示例:增强参数处理
public class TrimParameterFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 装饰原始request,添加trim功能
        HttpServletRequest wrappedRequest = new HttpServletRequestWrapper((HttpServletRequest) request) {
            @Override
            public String getParameter(String name) {
                String value = super.getParameter(name);
                return value != null ? value.trim() : null;
            }
        };
        // 传递装饰后的对象
        chain.doFilter(wrappedRequest, response);
    }
}

设计价值

  • 无需修改原始类(如HttpServletRequest的实现),通过包装实现功能增强;
  • 支持多层装饰:可通过多个装饰器叠加增强功能(如先 trim 参数,再过滤 XSS 攻击);
  • 灵活性高:根据需要动态选择是否增强、增强哪些功能。

三、行为型模式:规范对象的交互行为

行为型模式关注 “对象如何交互”,Spring 通过这些模式实现了框架的流程控制和行为扩展。

1. 模板方法模式:固定流程的 “骨架定义”

核心问题:如何定义一个流程的骨架,将可变步骤延迟到子类实现?

Spring 中的实现
AbstractBeanFactory定义了 Bean 创建的流程骨架,子类只需实现特定步骤:

// 抽象模板类
public abstract class AbstractBeanFactory implements BeanFactory {
    // 模板方法:定义Bean创建的完整流程(固定)
    @Override
    public final Object getBean(String name) throws BeansException {
        // 1. 检查缓存
        Object bean = getSingleton(name);
        if (bean != null) {
            return bean;
        }
        // 2. 获取Bean定义
        BeanDefinition bd = getBeanDefinition(name);
        // 3. 创建Bean(抽象方法,由子类实现)
        bean = createBean(name, bd);
        // 4. 初始化Bean(钩子方法,可选实现)
        bean = initializeBean(name, bean, bd);
        // 5. 放入缓存
        registerSingleton(name, bean);
        return bean;
    }
    
    // 抽象方法:创建Bean的具体逻辑(由子类实现)
    protected abstract Object createBean(String name, BeanDefinition bd) throws BeansException;
    
    // 钩子方法:初始化Bean(子类可覆盖)
    protected Object initializeBean(String name, Object bean, BeanDefinition bd) {
        // 默认空实现,子类可添加初始化逻辑(如调用init-method)
        return bean;
    }
    
    // 其他方法...
}

// 子类实现:具体创建Bean的逻辑
public class DefaultListableBeanFactory extends AbstractBeanFactory {
    @Override
    protected Object createBean(String name, BeanDefinition bd) throws BeansException {
        try {
            // 具体创建逻辑(如依赖注入)
            Object bean = bd.getBeanClass().newInstance();
            populateBean(bean, bd); // 填充属性
            return bean;
        } catch (Exception e) {
            throw new BeansException("创建Bean失败", e);
        }
    }
}

设计价值

  • 固定核心流程(如getBean的步骤),确保框架行为的一致性;
  • 可变步骤(如createBean)由子类实现,既保证了灵活性,又避免了流程逻辑的重复;
  • 钩子方法(如initializeBean)允许子类在特定节点添加自定义逻辑,无需修改模板方法。

2. 观察者模式:事件驱动的 “松耦合通信”

核心问题:如何实现组件间的 “发布 - 订阅” 通信,避免直接依赖?

Spring 中的实现
Spring 的事件机制基于观察者模式,通过ApplicationEvent(事件)、ApplicationListener(观察者)和
ApplicationEventMulticaster(事件发布器)实现:

// 事件基类
public abstract class ApplicationEvent {
    private final Object source;
    private final long timestamp;
    
    public ApplicationEvent(Object source) {
        this.source = source;
        this.timestamp = System.currentTimeMillis();
    }
    // getter...
}

// 自定义事件:用户注册事件
public class UserRegisteredEvent extends ApplicationEvent {
    private final String username;
    
    public UserRegisteredEvent(Object source, String username) {
        super(source);
        this.username = username;
    }
    // getter...
}

// 观察者接口
public interface ApplicationListener<E extends ApplicationEvent> {
    void onApplicationEvent(E event);
}

// 事件发布器
public class SimpleApplicationEventMulticaster {
    // 存储所有观察者
    private final Set<ApplicationListener<?>> listeners = new LinkedHashSet<>();
    
    // 注册观察者
    public void addApplicationListener(ApplicationListener<?> listener) {
        listeners.add(listener);
    }
    
    // 发布事件(通知所有观察者)
    public void multicastEvent(ApplicationEvent event) {
        for (ApplicationListener<?> listener : listeners) {
            // 检查观察者是否支持该事件
            if (supportsEvent(listener, event)) {
                ((ApplicationListener<ApplicationEvent>) listener).onApplicationEvent(event);
            }
        }
    }
    
    private boolean supportsEvent(ApplicationListener<?> listener, ApplicationEvent event) {
        // 简化逻辑:通过泛型判断
        return true;
    }
}

// 使用示例
public class UserService {
    private final SimpleApplicationEventMulticaster eventMulticaster;
    
    public UserService(SimpleApplicationEventMulticaster multicaster) {
        this.eventMulticaster = multicaster;
    }
    
    public void register(String username) {
        // 业务逻辑:注册用户
        System.out.println("用户注册:" + username);
        // 发布事件
        eventMulticaster.multicastEvent(new UserRegisteredEvent(this, username));
    }
}

// 观察者:发送欢迎邮件
public class EmailListener implements ApplicationListener<UserRegisteredEvent> {
    @Override
    public void onApplicationEvent(UserRegisteredEvent event) {
        System.out.println("发送欢迎邮件给:" + event.getUsername());
    }
}

设计价值

  • 实现了组件间的解耦:UserService发布事件后无需关心谁处理,观察者只需订阅事件即可;
  • 支持动态扩展:新增功能(如注册后发送短信)只需添加新的观察者,无需修改UserService;
  • 符合 “开闭原则”:对扩展开放(新增观察者),对修改关闭(不修改发布者)。

3. 责任链模式:请求处理的 “流水线作业”

核心问题:如何让多个处理器按顺序处理请求,且每个处理器可决定是否继续传递请求?

Spring 中的实现
Spring MVC 的拦截器链(HandlerInterceptor)通过责任链模式处理请求:

// 拦截器接口(责任链节点)
public interface HandlerInterceptor {
    // 前置处理:返回true则继续传递,false则中断
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    
    // 后置处理
    void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mv) throws Exception;
}

// 日志拦截器
public class LogInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("请求URL:" + request.getRequestURI());
        return true; // 继续传递
    }
}

// 权限拦截器
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader("token");
        if (token == null || "".equals(token)) {
            response.sendError(401, "未授权");
            return false; // 中断传递
        }
        return true; // 继续传递
    }
}

// 责任链管理器
public class HandlerExecutionChain {
    private final Object handler; // 目标处理器
    private final List<HandlerInterceptor> interceptors = new ArrayList<>();
    
    public HandlerExecutionChain(Object handler) {
        this.handler = handler;
    }
    
    public void addInterceptor(HandlerInterceptor interceptor) {
        interceptors.add(interceptor);
    }
    
    // 执行前置拦截器链
    public boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 按顺序执行所有拦截器
        for (HandlerInterceptor interceptor : interceptors) {
            if (!interceptor.preHandle(request, response, handler)) {
                // 若拦截器返回false,中断链
                return false;
            }
        }
        return true;
    }
}

// DispatcherServlet中使用责任链
public class DispatcherServlet {
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 获取处理器和拦截器链
        HandlerExecutionChain chain = getHandlerChain(request);
        // 执行前置拦截器
        if (!chain.applyPreHandle(request, response)) {
            return; // 被拦截,直接返回
        }
        // 执行处理器
        ModelAndView mv = handleRequest(request, response, chain.getHandler());
        // 执行后置拦截器...
    }
}

设计价值

  • 实现了请求处理的 “流水线化”,每个拦截器专注于单一职责(如日志、权限);
  • 拦截器顺序可动态调整,且可随时新增 / 移除拦截器,灵活性高;
  • 避免了请求发送者与多个处理器的直接耦合,符合迪米特法则。

四、总结:设计模式在 Spring 中的核心价值

Spring 框架的成功,离不开对设计模式的 “恰到好处” 的运用:

  • 创建型模式(工厂、单例、建造者)解决了 “对象创建” 的问题,实现了 IoC 容器的核心能力;
  • 结构型模式(代理、适配器、装饰器)解决了 “功能扩展” 的问题,让 AOP、MVC 等模块灵活且可扩展;
  • 行为型模式(模板方法、观察者、责任链)解决了 “流程控制” 的问题,规范了框架的执行逻辑。

这些模式的价值不仅在于 “解决问题”,更在于提供了一套 “设计语言”—— 让框架的代码结构清晰、逻辑可预测,同时降低了开发者的学习成本(掌握模式后,很容易理解 Spring 的设计思路)。

在手写 mini-spring 或其他框架时,不必刻意套用所有模式,而是要理解 “模式是为了解决特定问题而存在”。当遇到 “如何解耦对象创建”“如何动态扩展功能” 等问题时,再选择合适的模式,才能真正发挥设计模式的威力。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表