Spring ApplicationEventPublisher源码详解(详细注释版)

Spring ApplicationEventPublisher源码详解(详细注释版)

1. ApplicationEventPublisher接口源码

/*
 * ApplicationEventPublisher接口是Spring框架中用于发布应用事件的核心接口
 * 提供了统一的事件发布机制,支持观察者模式的实现
 * 是Spring事件驱动架构的基础
 * 
 * ApplicationEventPublisher的作用:
 * 1. 统一的事件发布入口
 * 2. 支持观察者模式
 * 3. 实现松耦合的组件通信
 * 4. 支持异步事件处理
 * 5. 提供事件过滤和路由能力
 * 
 * 注意事项:
 * - 事件发布是同步的(除非特别配置)
 * - 事件监听器应该快速执行
 * - 避免在事件监听器中执行耗时操作
 * - 注意事件处理的异常处理
 */
package org.springframework.context;

import org.springframework.lang.Nullable;

/**
 * 用于发布应用事件的接口
 * 
 * ApplicationEventPublisher在Spring框架中的作用:
 * 1. 提供事件发布机制
 * 2. 支持松耦合的组件通信
 * 3. 实现观察者模式
 * 4. 支持事件的层次化传播
 * 5. 与IoC容器集成
 * 
 * 事件发布流程:
 * 1. 组件调用publishEvent()发布事件
 * 2. ApplicationEventMulticaster接收事件
 * 3. 事件被分发给所有匹配的监听器
 * 4. 监听器处理事件
 * 
 * 支持的事件类型:
 * - ApplicationEvent的子类
 * - 任意对象(自动包装为PayloadApplicationEvent)
 */
public interface ApplicationEventPublisher {

    /**
     * 通知此应用程序中所有匹配的监听器指定的事件
     * 
     * 如果可能,事件将被发布到父上下文的监听器
     * 如果此ApplicationEventPublisher是ApplicationContext的实例,
     * 则会自动处理事件类型匹配和监听器调用
     * 
     * @param event 要发布的事件
     * 
     * 使用场景:
     * - 业务事件发布(用户创建、订单处理等)
     * - 系统事件发布(上下文刷新、关闭等)
     * - 自定义事件发布
     * - 组件间通信
     * 
     * 注意事项:
     * - 事件发布是同步的
     * - 监听器异常不会影响其他监听器
     * - 事件对象应该是不可变的
     */
    default void publishEvent(ApplicationEvent event) {
        publishEvent((Object) event);
    }

    /**
     * 通知此应用程序中所有匹配的监听器指定的事件
     * 
     * 如果可能,事件将被发布到父上下文的监听器
     * 如果发布的对象不是ApplicationEvent,则将其包装在PayloadApplicationEvent中
     * 
     * @param event 要发布的事件对象
     * 
     * 使用场景:
     * - 发布任意对象作为事件
     * - 简化事件创建过程
     * - 发布简单数据事件
     * 
     * 支持的事件对象类型:
     * - ApplicationEvent及其子类
     * - 任意Java对象(自动包装)
     * - 字符串、数字等基本类型
     */
    void publishEvent(Object event);

}

2. ApplicationEventMulticaster事件广播器

/*
 * ApplicationEventMulticaster接口是事件发布的具体实现
 * 负责将事件分发给所有注册的监听器
 */
package org.springframework.context.event;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 * 将应用事件多播到注册的ApplicationListener的策略
 * 
 * ApplicationEventMulticaster的主要职责:
 * 1. 管理监听器注册
 * 2. 事件分发给匹配的监听器
 * 3. 支持监听器的动态添加和移除
 * 4. 提供事件处理的配置选项
 * 
 * 实现类:
 * - SimpleApplicationEventMulticaster: 简单实现
 * - 可以扩展实现异步事件处理
 */
public interface ApplicationEventMulticaster {

    /**
     * 添加应用程序监听器以接收所有事件的通知
     * 
     * @param listener 要添加的ApplicationListener
     * 
     * 使用场景:
     * - 动态注册监听器
     * - 运行时添加事件处理逻辑
     * - 插件化架构支持
     */
    void addApplicationListener(ApplicationListener<?> listener);

    /**
     * 添加监听器Bean的名称以接收所有事件的通知
     * 
     * @param listenerBeanName 监听器Bean的名称
     * 
     * 使用场景:
     * - 延迟获取监听器实例
     * - 避免循环依赖
     * - 支持Bean生命周期管理
     */
    void addApplicationListenerBean(String listenerBeanName);

    /**
     * 从通知列表中移除应用程序监听器
     * 
     * @param listener 要移除的ApplicationListener
     * 
     * 使用场景:
     * - 动态移除监听器
     * - 运行时调整事件处理逻辑
     * - 资源清理
     */
    void removeApplicationListener(ApplicationListener<?> listener);

    /**
     * 从通知列表中移除监听器Bean的名称
     * 
     * @param listenerBeanName 要移除的监听器Bean名称
     * 
     * 使用场景:
     * - 移除延迟获取的监听器
     * - Bean销毁时的清理
     */
    void removeApplicationListenerBean(String listenerBeanName);

    /**
     * 移除所有已注册的监听器
     * 
     * 使用场景:
     * - 上下文关闭时的清理
     * - 重置事件处理系统
     * - 测试环境清理
     */
    void removeAllListeners();

    /**
     * 将给定的应用程序事件多播到适当的监听器
     * 
     * @param event 要多播的事件
     * 
     * 处理流程:
     * 1. 确定事件类型
     * 2. 查找匹配的监听器
     * 3. 调用监听器的onApplicationEvent方法
     * 4. 处理可能的异常
     */
    void multicastEvent(ApplicationEvent event);

    /**
     * 将给定的应用程序事件多播到适当的监听器
     * 
     * @param event 要多播的事件
     * @param eventType 事件类型(可为空)
     * 
     * 使用场景:
     * - 泛型事件处理
     * - 类型安全的事件分发
     * - 性能优化(避免类型推断)
     */
    void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);

}

3. SimpleApplicationEventMulticaster实现

/*
 * SimpleApplicationEventMulticaster是ApplicationEventMulticaster的简单实现
 * 提供了基本的事件多播功能
 */
package org.springframework.context.event;

import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.CopyOnWriteArraySet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * ApplicationEventMulticaster的简单实现
 * 
 * SimpleApplicationEventMulticaster提供以下功能:
 * 1. 监听器的注册和管理
 * 2. 事件的同步或异步分发
 * 3. 监听器的排序支持
 * 4. 异常处理机制
 * 5. BeanFactory集成
 * 
 * 特性:
 * - 线程安全的监听器管理
 * - 支持同步和异步事件处理
 * - 监听器排序支持
 * - 灵活的异常处理
 */
public class SimpleApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
    
    // 日志记录器
    protected final Log logger = LogFactory.getLog(getClass());
    
    // 监听器集合(线程安全)
    private final Set<ApplicationListener<?>> applicationListeners = new CopyOnWriteArraySet<>();
    
    // 监听器Bean名称集合
    private final Set<String> applicationListenerBeans = new LinkedHashSet<>();
    
    // BeanFactory引用
    @Nullable
    private BeanFactory beanFactory;
    
    // 任务执行器(用于异步事件处理)
    @Nullable
    private Executor taskExecutor;
    
    // 错误处理器
    @Nullable
    private ErrorHandler errorHandler;
    
    /**
     * 设置BeanFactory
     * 
     * @param beanFactory BeanFactory实例
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }
    
    /**
     * 获取BeanFactory
     * 
     * @return BeanFactory实例
     */
    @Nullable
    protected BeanFactory getBeanFactory() {
        return this.beanFactory;
    }
    
    /**
     * 设置任务执行器
     * 
     * @param taskExecutor 任务执行器
     * 
     * 使用场景:
     * - 异步事件处理
     * - 提高事件处理性能
     * - 避免阻塞事件发布线程
     */
    public void setTaskExecutor(@Nullable Executor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }
    
    /**
     * 获取任务执行器
     * 
     * @return 任务执行器
     */
    @Nullable
    protected Executor getTaskExecutor() {
        return this.taskExecutor;
    }
    
    /**
     * 设置错误处理器
     * 
     * @param errorHandler 错误处理器
     * 
     * 使用场景:
     * - 统一的异常处理
     * - 错误日志记录
     * - 错误恢复机制
     */
    public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }
    
    /**
     * 获取错误处理器
     * 
     * @return 错误处理器
     */
    @Nullable
    protected ErrorHandler getErrorHandler() {
        return this.errorHandler;
    }
    
    /**
     * 添加应用程序监听器
     */
    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        Assert.notNull(listener, "ApplicationListener must not be null");
        this.applicationListeners.add(listener);
    }
    
    /**
     * 添加监听器Bean名称
     */
    @Override
    public void addApplicationListenerBean(String listenerBeanName) {
        Assert.notNull(listenerBeanName, "Listener bean name must not be null");
        this.applicationListenerBeans.add(listenerBeanName);
    }
    
    /**
     * 移除应用程序监听器
     */
    @Override
    public void removeApplicationListener(ApplicationListener<?> listener) {
        Assert.notNull(listener, "ApplicationListener must not be null");
        this.applicationListeners.remove(listener);
    }
    
    /**
     * 移除监听器Bean名称
     */
    @Override
    public void removeApplicationListenerBean(String listenerBeanName) {
        Assert.notNull(listenerBeanName, "Listener bean name must not be null");
        this.applicationListenerBeans.remove(listenerBeanName);
    }
    
    /**
     * 移除所有监听器
     */
    @Override
    public void removeAllListeners() {
        this.applicationListeners.clear();
        this.applicationListenerBeans.clear();
    }
    
    /**
     * 多播事件(主要实现方法)
     */
    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        // 解析事件类型
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        
        // 获取匹配的监听器
        Collection<ApplicationListener<?>> listeners = getApplicationListeners(event, type);
        
        // 分发事件给每个监听器
        for (ApplicationListener<?> listener : listeners) {
            // 如果配置了任务执行器,异步执行
            if (this.taskExecutor != null) {
                try {
                    this.taskExecutor.execute(() -> invokeListener(listener, event));
                }
                catch (RejectedExecutionException ex) {
                    // 如果任务被拒绝,同步执行
                    invokeListener(listener, event);
                }
            }
            else {
                // 同步执行
                invokeListener(listener, event);
            }
        }
    }
    
    /**
     * 解析默认事件类型
     */
    private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
        return ResolvableType.forInstance(event);
    }
    
    /**
     * 调用监听器处理事件
     */
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        // 如果配置了错误处理器,使用它处理异常
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            }
            catch (Throwable err) {
                errorHandler.handleError(err);
            }
        }
        else {
            // 直接调用,异常会传播
            doInvokeListener(listener, event);
        }
    }
    
    /**
     * 实际调用监听器
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);
        }
        catch (ClassCastException ex) {
            // 类型转换异常,可能是泛型监听器类型不匹配
            String msg = ex.getMessage();
            if (msg == null || msg.indexOf("cannot be cast to") == -1) {
                throw ex;
            }
            // 静默忽略类型不匹配的异常
            logger.debug("Non-matching event type for listener: " + listener, ex);
        }
    }
    
    /**
     * 获取应用程序监听器
     */
    protected Collection<ApplicationListener<?>> getApplicationListeners(
            ApplicationEvent event, ResolvableType eventType) {

        // 获取所有监听器
        Set<ApplicationListener<?>> listeners = new LinkedHashSet<>();
        
        // 添加直接注册的监听器
        listeners.addAll(this.applicationListeners);
        
        // 添加通过Bean名称注册的监听器
        if (this.beanFactory != null) {
            for (String listenerBeanName : this.applicationListenerBeans) {
                try {
                    ApplicationListener<?> listener = this.beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    listeners.add(listener);
                }
                catch (NoSuchBeanDefinitionException ex) {
                    // 忽略不存在的Bean
                }
            }
        }
        
        // 过滤匹配的监听器
        Set<ApplicationListener<?>> filteredListeners = new LinkedHashSet<>();
        for (ApplicationListener<?> listener : listeners) {
            if (supportsEvent(listener, event, eventType)) {
                filteredListeners.add(listener);
            }
        }
        
        // 排序监听器
        AnnotationAwareOrderComparator.sort(filteredListeners);
        
        return filteredListeners;
    }
    
    /**
     * 判断监听器是否支持指定事件
     */
    protected boolean supportsEvent(
            ApplicationListener<?> listener, ApplicationEvent event, ResolvableType eventType) {

        // 获取监听器的泛型类型
        SmartApplicationListener smartListener = (listener instanceof SmartApplicationListener ?
                (SmartApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
        
        // 检查事件类型支持
        return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(event.getSource().getClass()));
    }
    
    /**
     * 多播事件(简化版本)
     */
    @Override
    public void multicastEvent(ApplicationEvent event) {
        multicastEvent(event, null);
    }
}

4. ApplicationEvent事件体系

/*
 * ApplicationEvent及其实现类
 * 提供了事件的基类和常用事件实现
 */

/**
 * ApplicationEvent是所有应用事件的基类
 * 
 * ApplicationEvent的设计原则:
 * 1. 不可变性:事件对象应该是不可变的
 * 2. 序列化支持:支持序列化以便远程传输
 * 3. 时间戳:记录事件发生时间
 * 4. 源对象:记录事件的来源
 */
public abstract class ApplicationEvent extends EventObject {

    // 事件发生的时间戳
    private final long timestamp;

    /**
     * 构造方法
     * 
     * @param source 事件的源对象
     */
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }

    /**
     * 获取事件发生的时间戳
     * 
     * @return 事件时间戳(毫秒)
     */
    public final long getTimestamp() {
        return this.timestamp;
    }
}

/**
 * PayloadApplicationEvent负载事件
 * 用于包装任意对象作为事件
 */
@SuppressWarnings("serial")
public class PayloadApplicationEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {

    // 负载对象
    private final T payload;

    /**
     * 构造方法
     * 
     * @param source 事件源
     * @param payload 负载对象
     */
    public PayloadApplicationEvent(Object source, T payload) {
        super(source);
        this.payload = payload;
    }

    /**
     * 获取负载对象
     * 
     * @return 负载对象
     */
    public T getPayload() {
        return this.payload;
    }

    /**
     * 获取可解析类型
     * 
     * @return 可解析类型
     */
    @Override
    @Nullable
    public ResolvableType getResolvableType() {
        return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getPayload()));
    }
}

/**
 * ApplicationContextEvent应用上下文事件
 * 应用上下文相关事件的基类
 */
@SuppressWarnings("serial")
public abstract class ApplicationContextEvent extends ApplicationEvent {

    /**
     * 构造方法
     * 
     * @param source 应用上下文
     */
    public ApplicationContextEvent(ApplicationContext source) {
        super(source);
    }

    /**
     * 获取应用上下文
     * 
     * @return 应用上下文
     */
    public final ApplicationContext getApplicationContext() {
        return (ApplicationContext) getSource();
    }
}

/**
 * ContextRefreshedEvent上下文刷新事件
 * 当ApplicationContext初始化或刷新时发布
 */
@SuppressWarnings("serial")
public class ContextRefreshedEvent extends ApplicationContextEvent {

    /**
     * 构造方法
     * 
     * @param source 应用上下文
     */
    public ContextRefreshedEvent(ApplicationContext source) {
        super(source);
    }
}

/**
 * ContextStartedEvent上下文启动事件
 * 当ApplicationContext启动时发布
 */
@SuppressWarnings("serial")
public class ContextStartedEvent extends ApplicationContextEvent {

    /**
     * 构造方法
     * 
     * @param source 应用上下文
     */
    public ContextStartedEvent(ApplicationContext source) {
        super(source);
    }
}

/**
 * ContextStoppedEvent上下文停止事件
 * 当ApplicationContext停止时发布
 */
@SuppressWarnings("serial")
public class ContextStoppedEvent extends ApplicationContextEvent {

    /**
     * 构造方法
     * 
     * @param source 应用上下文
     */
    public ContextStoppedEvent(ApplicationContext source) {
        super(source);
    }
}

/**
 * ContextClosedEvent上下文关闭事件
 * 当ApplicationContext关闭时发布
 */
@SuppressWarnings("serial")
public class ContextClosedEvent extends ApplicationContextEvent {

    /**
     * 构造方法
     * 
     * @param source 应用上下文
     */
    public ContextClosedEvent(ApplicationContext source) {
        super(source);
    }
}

/**
 * RequestHandledEvent请求处理事件
 * 当Web请求被处理时发布
 */
@SuppressWarnings("serial")
public class RequestHandledEvent extends ApplicationEvent {

    // 会话ID
    @Nullable
    private String sessionId;

    // 用户名
    @Nullable
    private String userName;

    // 处理时间
    private final long processingTimeMillis;

    // 请求方法
    private final String method;

    // 请求URI
    private final String requestUri;

    // 查询字符串
    @Nullable
    private String queryString;

    // 客户端地址
    private final String clientAddress;

    // 用户代理
    @Nullable
    private String userAgent;

    // 是否成功
    private final boolean success;

    // 失败原因
    @Nullable
    private String failureCause;

    /**
     * 构造方法
     * 
     * @param source 事件源
     * @param method 请求方法
     * @param requestUri 请求URI
     * @param processingTimeMillis 处理时间
     * @param clientAddress 客户端地址
     * @param success 是否成功
     */
    public RequestHandledEvent(Object source, String method, String requestUri,
            long processingTimeMillis, String clientAddress, boolean success) {

        super(source);
        this.method = method;
        this.requestUri = requestUri;
        this.processingTimeMillis = processingTimeMillis;
        this.clientAddress = clientAddress;
        this.success = success;
    }

    // Getters and Setters...
    public String getMethod() { return method; }
    public String getRequestUri() { return requestUri; }
    public long getProcessingTimeMillis() { return processingTimeMillis; }
    public String getClientAddress() { return clientAddress; }
    public boolean isSuccess() { return success; }
    
    @Nullable
    public String getSessionId() { return sessionId; }
    public void setSessionId(@Nullable String sessionId) { this.sessionId = sessionId; }
    
    @Nullable
    public String getUserName() { return userName; }
    public void setUserName(@Nullable String userName) { this.userName = userName; }
    
    @Nullable
    public String getQueryString() { return queryString; }
    public void setQueryString(@Nullable String queryString) { this.queryString = queryString; }
    
    @Nullable
    public String getUserAgent() { return userAgent; }
    public void setUserAgent(@Nullable String userAgent) { this.userAgent = userAgent; }
    
    @Nullable
    public String getFailureCause() { return failureCause; }
    public void setFailureCause(@Nullable String failureCause) { this.failureCause = failureCause; }
}

5. ApplicationListener监听器体系

/*
 * ApplicationListener及其实现
 * 提供了事件监听的接口和实现
 */

/**
 * ApplicationListener事件监听器接口
 * 
 * ApplicationListener的设计原则:
 * 1. 类型安全:支持泛型事件监听
 * 2. 单一职责:每个监听器处理特定类型的事件
 * 3. 无状态:监听器应该是无状态的或线程安全的
 * 4. 快速执行:监听器应该快速完成处理
 */
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

    /**
     * 处理应用事件
     * 
     * @param event 要响应的事件
     */
    void onApplicationEvent(E event);
}

/**
 * SmartApplicationListener智能应用监听器
 * 提供更高级的事件监听能力
 */
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {

    /**
     * 判断监听器是否支持指定的事件类型
     * 
     * @param eventType 事件类型
     * @return 如果支持返回true
     */
    boolean supportsEventType(ResolvableType eventType);

    /**
     * 判断监听器是否支持指定的源类型
     * 
     * @param sourceType 源类型
     * @return 如果支持返回true
     */
    boolean supportsSourceType(@Nullable Class<?> sourceType);

    /**
     * 获取监听器的顺序
     * 
     * @return 顺序值
     */
    @Override
    default int getOrder() {
        return LOWEST_PRECEDENCE;
    }
}

/**
 * GenericApplicationListenerAdapter泛型监听器适配器
 * 将普通ApplicationListener适配为SmartApplicationListener
 */
public class GenericApplicationListenerAdapter implements SmartApplicationListener {

    // 目标监听器
    private final ApplicationListener<ApplicationEvent> delegate;

    // 事件类型
    @Nullable
    private final ResolvableType declaredEventType;

    /**
     * 构造方法
     * 
     * @param delegate 目标监听器
     */
    @SuppressWarnings("unchecked")
    public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
        this.delegate = (ApplicationListener<ApplicationEvent>) delegate;
        this.declaredEventType = resolveDeclaredEventType(this.delegate);
    }

    /**
     * 解析声明的事件类型
     */
    @Nullable
    static ResolvableType resolveDeclaredEventType(ApplicationListener<?> listener) {
        ResolvableType eventType = ResolvableType.forClass(ApplicationListener.class, listener.getClass());
        if (eventType.hasGenerics()) {
            return eventType.getGeneric();
        }
        return null;
    }

    /**
     * 判断是否支持事件类型
     */
    @Override
    public boolean supportsEventType(ResolvableType eventType) {
        if (this.declaredEventType == null) {
            return true;
        }
        return (eventType.getRawClass() != null && 
                ClassUtils.isAssignable(this.declaredEventType.getRawClass(), eventType.getRawClass()));
    }

    /**
     * 判断是否支持源类型
     */
    @Override
    public boolean supportsSourceType(@Nullable Class<?> sourceType) {
        return true;
    }

    /**
     * 处理应用事件
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        this.delegate.onApplicationEvent(event);
    }

    /**
     * 获取顺序
     */
    @Override
    public int getOrder() {
        return (this.delegate instanceof Ordered ? ((Ordered) this.delegate).getOrder() : LOWEST_PRECEDENCE);
    }
}

/**
 * ApplicationListenerDetector应用监听器检测器
 * 用于检测和注册Bean中的监听器
 */
class ApplicationListenerDetector implements BeanPostProcessor, DestructionAwareBeanPostProcessor {

    // 应用上下文
    private final AbstractApplicationContext applicationContext;

    /**
     * 构造方法
     * 
     * @param applicationContext 应用上下文
     */
    public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    /**
     * 初始化后处理
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (bean instanceof ApplicationListener) {
            // 将ApplicationListener注册到ApplicationContext
            Boolean flag = this.applicationContext.getSingleton(beanName);
            if (Boolean.TRUE.equals(flag)) {
                // singleton bean
                this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
            }
            else if (flag == null) {
                // prototype bean
                this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
            }
        }
        return bean;
    }

    /**
     * 销毁前处理
     */
    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) {
        if (bean instanceof ApplicationListener) {
            try {
                ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
                multicaster.removeApplicationListener((ApplicationListener<?>) bean);
            }
            catch (IllegalStateException ex) {
                // ApplicationEventMulticaster not initialized yet - no need to remove
            }
        }
    }

    /**
     * 判断是否需要销毁处理
     */
    @Override
    public boolean requiresDestruction(Object bean) {
        return (bean instanceof ApplicationListener);
    }
}

6. 实际使用示例

/*
 * ApplicationEventPublisher实际使用示例
 */

/**
 * 自定义业务事件
 */
public class UserCreatedEvent extends ApplicationEvent {
    
    private final User user;
    private final String sourceSystem;
    
    /**
     * 构造方法
     * 
     * @param source 事件源
     * @param user 创建的用户
     * @param sourceSystem 源系统
     */
    public UserCreatedEvent(Object source, User user, String sourceSystem) {
        super(source);
        this.user = user;
        this.sourceSystem = sourceSystem;
    }
    
    // Getters
    public User getUser() { return user; }
    public String getSourceSystem() { return sourceSystem; }
}

/**
 * 用户实体类
 */
public class User {
    private Long id;
    private String name;
    private String email;
    private Date createTime;
    
    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.createTime = new Date();
    }
    
    // Getters and Setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public Date getCreateTime() { return createTime; }
    public void setCreateTime(Date createTime) { this.createTime = createTime; }
}

/**
 * 用户服务类
 */
@Service
public class UserService {
    
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    
    // 注入事件发布器
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    /**
     * 创建用户
     * 
     * @param name 用户名
     * @param email 邮箱
     * @return 创建的用户
     */
    public User createUser(String name, String email) {
        logger.info("开始创建用户: {}, {}", name, email);
        
        // 创建用户逻辑
        User user = new User(System.currentTimeMillis(), name, email);
        
        // 发布用户创建事件
        UserCreatedEvent event = new UserCreatedEvent(this, user, "UserService");
        eventPublisher.publishEvent(event);
        
        logger.info("用户创建完成: {}", user.getId());
        return user;
    }
    
    /**
     * 批量创建用户
     * 
     * @param users 用户列表
     */
    public void createUsers(List<User> users) {
        for (User user : users) {
            createUser(user.getName(), user.getEmail());
        }
    }
}

/**
 * 邮件服务监听器
 */
@Component
public class EmailServiceListener {
    
    private static final Logger logger = LoggerFactory.getLogger(EmailServiceListener.class);
    
    /**
     * 监听用户创建事件
     * 
     * @param event 用户创建事件
     */
    @EventListener
    @Order(1) // 设置监听器顺序
    public void handleUserCreated(UserCreatedEvent event) {
        User user = event.getUser();
        String sourceSystem = event.getSourceSystem();
        
        logger.info("收到用户创建事件: 用户={}, 源系统={}", user.getName(), sourceSystem);
        
        try {
            // 发送欢迎邮件
            sendWelcomeEmail(user);
        } catch (Exception e) {
            logger.error("发送欢迎邮件失败: 用户={}", user.getName(), e);
        }
    }
    
    /**
     * 发送欢迎邮件
     * 
     * @param user 用户
     */
    private void sendWelcomeEmail(User user) {
        logger.info("发送欢迎邮件给用户: {} ({})", user.getName(), user.getEmail());
        // 实际的邮件发送逻辑
        try {
            // 模拟邮件发送耗时
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

/**
 * 日志服务监听器
 */
@Component
public class LoggingServiceListener {
    
    private static final Logger auditLogger = LoggerFactory.getLogger("AUDIT");
    
    /**
     * 监听用户创建事件
     * 
     * @param event 用户创建事件
     */
    @EventListener
    @Order(2) // 设置监听器顺序
    public void handleUserCreated(UserCreatedEvent event) {
        User user = event.getUser();
        String sourceSystem = event.getSourceSystem();
        
        // 记录审计日志
        auditLogger.info("用户创建审计: ID={}, 姓名={}, 邮箱={}, 源系统={}, 时间={}",
                user.getId(), user.getName(), user.getEmail(), 
                sourceSystem, new Date(event.getTimestamp()));
    }
    
    /**
     * 监听上下文刷新事件
     * 
     * @param event 上下文刷新事件
     */
    @EventListener
    public void handleContextRefresh(ContextRefreshedEvent event) {
        auditLogger.info("应用上下文刷新完成: {}", event.getApplicationContext().getDisplayName());
    }
    
    /**
     * 监听上下文关闭事件
     * 
     * @param event 上下文关闭事件
     */
    @EventListener
    public void handleContextClosed(ContextClosedEvent event) {
        auditLogger.info("应用上下文关闭: {}", event.getApplicationContext().getDisplayName());
    }
}

/**
 * 统计服务监听器
 */
@Component
public class StatisticsServiceListener {
    
    private static final Logger logger = LoggerFactory.getLogger(StatisticsServiceListener.class);
    
    // 用户创建计数器
    private final AtomicLong userCreateCount = new AtomicLong(0);
    
    /**
     * 监听用户创建事件
     * 
     * @param event 用户创建事件
     */
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        long count = userCreateCount.incrementAndGet();
        if (count % 100 == 0) { // 每100个用户记录一次统计
            logger.info("用户创建统计: 已创建 {} 个用户", count);
        }
    }
    
    /**
     * 获取用户创建总数
     * 
     * @return 用户创建总数
     */
    public long getUserCreateCount() {
        return userCreateCount.get();
    }
    
    /**
     * 重置计数器
     */
    public void resetCount() {
        userCreateCount.set(0);
    }
}

/**
 * 异步事件监听器
 */
@Component
public class AsyncEventListener {
    
    private static final Logger logger = LoggerFactory.getLogger(AsyncEventListener.class);
    
    /**
     * 异步监听用户创建事件
     * 
     * @param event 用户创建事件
     */
    @EventListener
    @Async // 异步执行
    public void handleUserCreatedAsync(UserCreatedEvent event) {
        User user = event.getUser();
        
        logger.info("异步处理用户创建事件: 用户={}, 线程={}", 
                   user.getName(), Thread.currentThread().getName());
        
        try {
            // 模拟耗时操作
            Thread.sleep(2000);
            logger.info("异步处理完成: 用户={}", user.getName());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("异步处理被中断: 用户={}", user.getName());
        }
    }
}

/**
 * 条件化事件监听器
 */
@Component
@Profile("production") // 仅在生产环境生效
public class ProductionEventListener {
    
    private static final Logger logger = LoggerFactory.getLogger(ProductionEventListener.class);
    
    /**
     * 监听用户创建事件
     * 
     * @param event 用户创建事件
     */
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        logger.info("生产环境专用监听器处理用户创建事件");
        // 生产环境特有的处理逻辑
    }
}

/**
 * 泛型事件监听器
 */
@Component
public class GenericEventListener {
    
    private static final Logger logger = LoggerFactory.getLogger(GenericEventListener.class);
    
    /**
     * 监听所有PayloadApplicationEvent事件
     * 
     * @param event 负载事件
     */
    @EventListener
    public void handlePayloadEvent(PayloadApplicationEvent<?> event) {
        Object payload = event.getPayload();
        logger.debug("收到负载事件: 负载类型={}, 负载内容={}", 
                    payload.getClass().getSimpleName(), payload);
    }
    
    /**
     * 监听特定类型的负载事件
     * 
     * @param event 字符串负载事件
     */
    @EventListener
    public void handleStringPayload(PayloadApplicationEvent<String> event) {
        String payload = event.getPayload();
        logger.info("收到字符串负载事件: {}", payload);
    }
}

/**
 * 应用程序主类
 */
@SpringBootApplication
@EnableAsync // 启用异步支持
public class EventApplication {
    
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(EventApplication.class, args);
        
        // 测试事件发布
        testEventPublishing(context);
        
        // 测试异步事件
        testAsyncEvents(context);
        
        // 测试负载事件
        testPayloadEvents(context);
        
        // 等待异步处理完成
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        // 查看统计信息
        StatisticsServiceListener statsListener = context.getBean(StatisticsServiceListener.class);
        logger.info("总用户创建数: {}", statsListener.getUserCreateCount());
        
        context.close();
    }
    
    /**
     * 测试事件发布
     */
    private static void testEventPublishing(ConfigurableApplicationContext context) {
        logger.info("=== 测试事件发布 ===");
        
        UserService userService = context.getBean(UserService.class);
        
        // 创建单个用户
        User user1 = userService.createUser("张三", "zhangsan@example.com");
        logger.info("创建用户: {}", user1.getName());
        
        // 批量创建用户
        List<User> users = Arrays.asList(
            new User(2L, "李四", "lisi@example.com"),
            new User(3L, "王五", "wangwu@example.com")
        );
        userService.createUsers(users);
        
        logger.info("事件发布测试完成");
    }
    
    /**
     * 测试异步事件
     */
    private static void testAsyncEvents(ConfigurableApplicationContext context) {
        logger.info("=== 测试异步事件 ===");
        
        ApplicationEventPublisher publisher = context;
        
        // 发布异步事件
        User user = new User(4L, "赵六", "zhaoliu@example.com");
        UserCreatedEvent event = new UserCreatedEvent("test", user, "AsyncTest");
        publisher.publishEvent(event);
        
        logger.info("异步事件已发布");
    }
    
    /**
     * 测试负载事件
     */
    private static void testPayloadEvents(ConfigurableApplicationContext context) {
        logger.info("=== 测试负载事件 ===");
        
        ApplicationEventPublisher publisher = context;
        
        // 发布字符串负载事件
        publisher.publishEvent("这是一个测试消息");
        
        // 发布数字负载事件
        publisher.publishEvent(42);
        
        // 发布对象负载事件
        publisher.publishEvent(new Date());
        
        logger.info("负载事件测试完成");
    }
}

/**
 * 配置类
 */
@Configuration
@EnableAsync
public class EventConfig {
    
    /**
     * 配置异步任务执行器
     */
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("Async-Event-");
        executor.initialize();
        return executor;
    }
    
    /**
     * 配置事件广播器
     */
    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster() {
        SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
        eventMulticaster.setTaskExecutor(taskExecutor());
        eventMulticaster.setErrorHandler(new CustomErrorHandler());
        return eventMulticaster;
    }
    
    /**
     * 自定义错误处理器
     */
    public static class CustomErrorHandler implements ErrorHandler {
        
        private static final Logger logger = LoggerFactory.getLogger(CustomErrorHandler.class);
        
        @Override
        public void handleError(Throwable t) {
            logger.error("事件处理过程中发生错误", t);
        }
    }
}

7. 最佳实践和注意事项

/*
 * ApplicationEventPublisher最佳实践
 */

/**
 * 正确的事件使用方式
 */
@Component
public class GoodEventUsage {
    
    private static final Logger logger = LoggerFactory.getLogger(GoodEventUsage.class);
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    /**
     * 正确的事件发布
     */
    public void correctEventPublishing() {
        try {
            // 创建用户
            User user = new User(1L, "测试用户", "test@example.com");
            
            // 发布事件
            UserCreatedEvent event = new UserCreatedEvent(this, user, "GoodEventUsage");
            eventPublisher.publishEvent(event);
            
            logger.info("事件发布成功: 用户={}", user.getName());
        } catch (Exception e) {
            logger.error("事件发布失败", e);
            // 适当的异常处理
        }
    }
    
    /**
     * 正确的事件监听器实现
     */
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        User user = event.getUser();
        
        // 快速验证
        if (user == null) {
            logger.warn("收到空用户事件");
            return;
        }
        
        try {
            // 快速执行的业务逻辑
            processUserCreation(user);
        } catch (Exception e) {
            // 记录错误但不传播异常
            logger.error("处理用户创建事件失败: 用户={}", user.getName(), e);
        }
    }
    
    /**
     * 处理用户创建
     */
    private void processUserCreation(User user) {
        // 快速执行的逻辑
        logger.info("处理用户创建: {}", user.getName());
        
        // 避免耗时操作,如:
        // - 数据库操作(应异步处理)
        // - 网络调用(应异步处理)
        // - 文件I/O(应异步处理)
    }
    
    /**
     * 异步事件监听器
     */
    @EventListener
    @Async
    public void handleUserCreatedAsync(UserCreatedEvent event) {
        User user = event.getUser();
        
        try {
            // 耗时操作可以在这里执行
            performTimeConsumingOperation(user);
        } catch (Exception e) {
            logger.error("异步处理用户创建失败: 用户={}", user.getName(), e);
        }
    }
    
    /**
     * 执行耗时操作
     */
    private void performTimeConsumingOperation(User user) {
        try {
            // 模拟耗时操作
            Thread.sleep(1000);
            logger.info("耗时操作完成: 用户={}", user.getName());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("耗时操作被中断: 用户={}", user.getName());
        }
    }
}

/**
 * 避免的错误使用方式
 */
@Component
public class BadEventUsage {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    /**
     * 错误的事件发布
     */
    public void badEventPublishing() {
        // 错误1: 发布可变对象
        User user = new User(1L, "测试用户", "test@example.com");
        user.setName("修改后的名称"); // 对象在发布后被修改
        
        UserCreatedEvent event = new UserCreatedEvent(this, user, "BadEventUsage");
        eventPublisher.publishEvent(event); // 可能导致不一致
        
        // 错误2: 不处理异常
        // eventPublisher.publishEvent(event); // 可能抛出异常
        
        // 错误3: 发布null事件
        // eventPublisher.publishEvent(null); // 会抛出异常
    }
    
    /**
     * 错误的事件监听器实现
     */
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        User user = event.getUser();
        
        // 错误1: 不验证输入
        // processUser(user); // user可能为null
        
        // 错误2: 执行耗时操作
        performTimeConsumingOperation(user); // 阻塞事件发布线程
        
        // 错误3: 传播异常
        // throw new RuntimeException("模拟异常"); // 影响其他监听器
    }
    
    /**
     * 错误的耗时操作
     */
    private void performTimeConsumingOperation(User user) {
        try {
            // 模拟耗时操作
            Thread.sleep(5000); // 长时间阻塞
            logger.info("耗时操作完成");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

/**
 * 线程安全的事件处理
 */
@Component
public class ThreadSafeEventHandling {
    
    private static final Logger logger = LoggerFactory.getLogger(ThreadSafeEventHandling.class);
    
    // 使用线程安全的集合
    private final ConcurrentHashMap<String, User> userCache = new ConcurrentHashMap<>();
    private final AtomicLong eventCounter = new AtomicLong(0);
    
    /**
     * 线程安全的事件监听器
     */
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        User user = event.getUser();
        
        // 线程安全的操作
        userCache.put(user.getId().toString(), user);
        long count = eventCounter.incrementAndGet();
        
        if (count % 1000 == 0) {
            logger.info("已处理 {} 个用户创建事件", count);
        }
    }
    
    /**
     * 获取用户(线程安全)
     */
    public User getUser(String userId) {
        return userCache.get(userId);
    }
    
    /**
     * 获取事件计数(线程安全)
     */
    public long getEventCount() {
        return eventCounter.get();
    }
    
    /**
     * 清理缓存
     */
    public void clearCache() {
        userCache.clear();
        eventCounter.set(0);
    }
}

/**
 * 条件化事件处理
 */
@Component
public class ConditionalEventHandling {
    
    private static final Logger logger = LoggerFactory.getLogger(ConditionalEventHandling.class);
    
    /**
     * 条件化的事件监听
     */
    @EventListener(condition = "#event.user.name.startsWith('A')")
    public void handleUserCreatedWithCondition(UserCreatedEvent event) {
        User user = event.getUser();
        logger.info("处理以A开头的用户名: {}", user.getName());
        // 只处理用户名以A开头的用户
    }
    
    /**
     * 基于SpEL表达式的条件监听
     */
    @EventListener(condition = "#event.user.email.endsWith('example.com')")
    public void handleCorporateUserCreated(UserCreatedEvent event) {
        User user = event.getUser();
        logger.info("处理企业用户: {}", user.getEmail());
        // 只处理企业邮箱用户
    }
    
    /**
     * 监听多个事件类型
     */
    @EventListener
    public void handleMultipleEvents(Object event) {
        if (event instanceof UserCreatedEvent) {
            handleUserCreatedEvent((UserCreatedEvent) event);
        } else if (event instanceof ContextRefreshedEvent) {
            handleContextRefreshedEvent((ContextRefreshedEvent) event);
        }
    }
    
    private void handleUserCreatedEvent(UserCreatedEvent event) {
        logger.info("处理用户创建事件");
    }
    
    private void handleContextRefreshedEvent(ContextRefreshedEvent event) {
        logger.info("处理上下文刷新事件");
    }
}

/**
 * 自定义事件广播器
 */
public class CustomApplicationEventMulticaster extends SimpleApplicationEventMulticaster {
    
    private static final Logger logger = LoggerFactory.getLogger(CustomApplicationEventMulticaster.class);
    
    // 事件处理统计
    private final AtomicLong eventCount = new AtomicLong(0);
    private final ConcurrentHashMap<String, AtomicLong> eventTypeCount = new ConcurrentHashMap<>();
    
    /**
     * 重写事件多播方法
     */
    @Override
    public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
        long count = eventCount.incrementAndGet();
        String eventTypeName = event.getClass().getSimpleName();
        eventTypeCount.computeIfAbsent(eventTypeName, k -> new AtomicLong(0))
                     .incrementAndGet();
        
        if (count % 1000 == 0) {
            logger.info("已处理 {} 个事件", count);
        }
        
        long startTime = System.currentTimeMillis();
        try {
            super.multicastEvent(event, eventType);
        } finally {
            long duration = System.currentTimeMillis() - startTime;
            if (duration > 1000) { // 超过1秒的事件处理
                logger.warn("事件处理耗时较长: 事件={}, 耗时={}ms", eventTypeName, duration);
            }
        }
    }
    
    /**
     * 获取事件统计信息
     */
    public Map<String, Long> getEventStatistics() {
        Map<String, Long> statistics = new HashMap<>();
        statistics.put("totalEvents", eventCount.get());
        eventTypeCount.forEach((type, counter) -> 
            statistics.put(type, counter.get()));
        return statistics;
    }
    
    /**
     * 重置统计信息
     */
    public void resetStatistics() {
        eventCount.set(0);
        eventTypeCount.clear();
    }
}

/**
 * 异常安全的事件处理
 */
@Component
public class ExceptionSafeEventHandling {
    
    private static final Logger logger = LoggerFactory.getLogger(ExceptionSafeEventHandling.class);
    
    /**
     * 异常安全的事件监听器
     */
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        try {
            processEventSafely(event);
        } catch (Exception e) {
            handleEventException(event, e);
        }
    }
    
    /**
     * 安全的事件处理
     */
    private void processEventSafely(UserCreatedEvent event) {
        User user = event.getUser();
        
        // 验证输入
        if (user == null) {
            throw new IllegalArgumentException("用户不能为空");
        }
        
        // 处理逻辑
        logger.info("处理用户创建事件: 用户={}", user.getName());
        
        // 模拟可能的异常
        if (user.getName().contains("error")) {
            throw new RuntimeException("模拟处理异常");
        }
    }
    
    /**
     * 处理事件异常
     */
    private void handleEventException(UserCreatedEvent event, Exception e) {
        User user = event.getUser();
        String userName = (user != null) ? user.getName() : "未知用户";
        
        logger.error("处理用户创建事件时发生异常: 用户={}, 异常={}", userName, e.getMessage(), e);
        
        // 可以选择:
        // 1. 记录错误日志
        // 2. 发送告警通知
        // 3. 重试处理
        // 4. 存储到错误队列
    }
}

8. 核心设计要点总结

8.1 设计目的

  • 提供统一的事件发布和监听机制
  • 实现松耦合的组件通信
  • 支持观察者模式
  • 提供事件的层次化传播
  • 支持同步和异步事件处理

8.2 核心组件

  • ApplicationEventPublisher: 事件发布接口
  • ApplicationEventMulticaster: 事件广播器
  • ApplicationListener: 事件监听器
  • ApplicationEvent: 事件基类
  • SmartApplicationListener: 智能监听器

8.3 事件处理流程

  1. 事件发布: 组件调用publishEvent()发布事件
  2. 事件广播: ApplicationEventMulticaster接收事件
  3. 监听器匹配: 根据事件类型匹配监听器
  4. 事件分发: 调用匹配监听器的onApplicationEvent方法
  5. 结果处理: 处理可能的异常和返回值

8.4 支持的特性

  • 同步/异步处理: 支持同步和异步事件处理
  • 事件过滤: 支持基于条件的事件过滤
  • 监听器排序: 支持监听器执行顺序控制
  • 异常处理: 提供统一的异常处理机制
  • 泛型支持: 支持泛型事件监听
  • 层次化传播: 支持事件在上下文层次中的传播

8.5 使用建议

  • 事件对象不可变: 确保事件对象在发布后不被修改
  • 监听器快速执行: 避免在监听器中执行耗时操作
  • 异常处理: 适当处理监听器中的异常
  • 线程安全: 确保监听器的线程安全性
  • 资源清理: 在适当时候清理监听器资源

8.6 最佳实践

  • 使用@EventListener注解简化监听器实现
  • 合理使用@Async实现异步事件处理
  • 实现适当的事件过滤和条件处理
  • 使用SmartApplicationListener实现智能监听
  • 提供统一的异常处理机制
  • 监控事件处理性能和统计信息
  • 避免循环事件发布

ApplicationEventPublisher作为Spring框架的核心组件,为开发者提供了强大而灵活的事件驱动架构支持,是构建松耦合、可扩展应用的重要工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值