IoC(Inverse of Control,控制反转)是 Spring 容器的内核,它是指某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定,即由 Spring 容器借由 Bean 配置来进行控制。由于 IoC 不好理解,后来人们提出了 DI(Dependency Injection,依赖注入)的概念,即让调用类对某一接口实现类的依赖关系由第三方注入,以移除调用者对某一接口实现类的依赖。Spring 通过配置文件或注解描述类和类之前的依赖关系,自动完成类的初始化和依赖注入工作。
BeanFactory
Spring 会利用反射实例化 Bean 并建立 Bean 之间的依赖关系。Spring 的 IoC 容器在完成这些底层工作的基础之上,还提供了 Bean 实例缓存、生命周期管理、Bean 实例代理、事件发布、资源装载等高级服务。
BeanFactory 是 Spring 最核心的接口,提供了高级 IoC 的配置机制,它使得管理不同类型的 Java 对象成为可能。而 ApplicationContext 建立在 BeanFactory 基础之上,提供了更多面向应用的功能。BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者。
BeanFactory 接口位于类结构树的顶端,它最主要的方法是 getBean(String name) 用于从容器中返回特定名称的 Bean。BeanFactory 的功能通过其子类接口得到不断扩展。
ListableBeanFactory:该接口定义了访问容器中 Bean 基本信息的若干方法,如查看 Bean 的个数、获取某一类型 Bean 的配置名等。
ConfigurableBeanFactory:该接口增强了 IoC 容器的可定制性。它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法。
AutowireCapableBeanFactory:定义了将容器中的 Bean 按某种规则(名字、类型等)进行自动装配的方法。
SingletonBeanRegistry:定义了允许在运行期向容器注册单实例 Bean 的方法。
BeanDefinitionRegistry:每一个
节点元素在 Spring 容器里都通过一个 BeanDefinition 对象表示,它描述了 Bean 的配置信息。而 BeanDefinitionRegistry 接口提供了向容器手工注册 BeanDefinition 对象的方法。
ApplicationContext
ApplicationContext 继承了 BeanFactory ,提供了更多面向实际应用的功能。它的主要实现类是 ClassPathXmlApplicationContext(默认从类路径加载配置文件)和 FileSystemXmlApplicationContext(默认从文件系统中装载配置文件)。以及为基于注解的 Bean 配置提供了专门的 AnnotationConfigApplicationContext。
在获取 ApplicationContext 实例后,就可以像 BeanFactory 一样获取 Bean 实例。但是 ApplicationContext 的初始化和 BeanFactory 有一个重大区别:
- BeanFactory 初始化容器时,并未实例化 Bean,直到第一次访问某个 Bean 时才实例化目标 Bean。
- ApplicationContext 初始化应用上下文时就实例化所有单例 Bean,因此初始化时间会久一点,但之后的调用则没有“第一次惩罚”的问题。
1. BeanFactoryPostProcessor
ApplicationContext 在启动时,将首先为配置文件中的每个
public interface BeanFactoryPostProcessor {
/**
* 在标准初始化之后修改应用程序上下文的内部bean工厂,此时所有bean定义都将被加载,但还没有bean被实例化,这允许覆盖或添加自定义bean定义
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
比如,Spring 内部提供了一个 PropertyPlaceholderConfigurer,它能够使 Bean 在配置时引用外部属性文件。该类就实现了 BeanFactoryPostProcessor 接口,因而也属于一个 Bean 工厂后置处理器。这样,基于注解配置的 Bean 就可以通过 @Value("${XXX}") 注解为 Bean 的成员变量或方法入参自动注入容器已有的属性了。如果想要注入其他 Bean 的属性,可以通过 @Value("#{beanName.propName}") 表达式来引用。
ApplicationContext 和 BeanFactory 另一个最大的不同之处在于:前者会利用 Java 反射机制自动识别出配置文件中定义的 BeanPostProcessor、InstantiationAwareBeanPostProcessor 和 BeanFactoryPostProcessor,并自动将它们注册到应用上下文中;而后者需要在代码中通过手工调用 addBeanPostProcessor() 方法进行注册。
2. 容器构建过程
Spring 的 AbstractApplicationContext 是 ApplicationContext 的抽象实现类,该抽象类的 refresh() 方法定义了 Spring 容器在加载配置文件后的各项处理过程。
public void refresh() throws BeansException, IllegalStateException {
// 整个过程进行线程同步处理
synchronized (this.startupShutdownMonitor) {
// 准备刷新的上下文环境
prepareRefresh();
// 初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 对BeanFactory进行各种功能填充
prepareBeanFactory(beanFactory);
try {
// 允许context的子类对bean工厂进行后置处理
postProcessBeanFactory(beanFactory);
// 激活各种BeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessors,这里只是注册,真正的调用是在getBean的时候
registerBeanPostProcessors(beanFactory);
// 初始化context的信息源,即不同语言的消息体,和国际化有关
initMessageSource();
// 初始化context的事件传播器
initApplicationEventMulticaster();
// 留给子类来初始化其它的Bean,这是一个钩子方法,子类可以借助这个方法执行一些特殊的操作
onRefresh();
// 在所有注册的bean中查找ApplicationListener bean,注册到消息广播器中
registerListeners();
// 实例化所有非懒加载单例
finishBeanFactoryInitialization(beanFactory);
// 完成刷新过程,发布对应容器刷新事件
finishRefresh();
}
......
}
}
2.1 obtainFreshBeanFactory
obtainFreshBeanFactory 方法从字面理解是获取 BeanFactory。之前有说过,ApplicationContext 是对 BeanFactory 的功能上的扩展,不但包含了 BeanFactory 的全部功能,更在其基础上添加了大量的扩展应用,那么 obtainFreshBeanFactory 正是实现 BeanFactory 的地方,经过了这个函数后 ApplicationContext 就已经拥有了 BeanFactory 的全部功能了。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
在 obtainFreshBeanFactory() 方法中,核心逻辑在 refreshBeanFactory() 方法中,这个方法是由子类来实现具体逻辑的,此时 Bean 实例还未初始化。
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// BeanFactory的原始对象类型,即DefaultListableBeanFactory类型
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为了序列化指定id,如果需要的话,让这个BeanFactory从id反序列到BeanFactory对象
beanFactory.setSerializationId(getId());
// 定制BeanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖
customizeBeanFactory(beanFactory);
// 加载、解析bean的定义,也就是把用户定义的数据结构转化为Ioc容器中的特定数据结构
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
2.2 prepareBeanFactory
进入函数 prepareBeanFactory 前,Spring 已经完成了对配置的解析,而 ApplicationContext 在功能上的扩展也由此展开。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 beanFactory 的 classLoader 为当前 context 的 classLoader
beanFactory.setBeanClassLoader(getClassLoader());
// 设置 beanFactory 的表达式语言处理器,默认可以使用#{bean.xxx}的形式来调用相关属性值
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加 BeanPostProcessor 处理器,用于回调Aware相关接口
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 设置了几个忽略自动装配的接口
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// 设置了几个自动装配的特殊规则
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 添加 BeanPostProcessor 处理器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 增加对 AspectJ 的支持
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 添加默认的系统环境bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
2.3 invokeBeanFactoryPostProcessors
从 BeanDefinitionRegistry 中找出所有实现了 BeanFactoryPostProcessor 接口的 Bean,然后通过反射机制进行实例化,并调用其 postProcessBeanFactory() 方法执行自定义逻辑。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
......
}
2.4 registerBeanPostProcessors
BeanPostProcessor 真正被调用其实是在 bean 的实例化阶段进行的,这里只是进行注册,但这是一个很重要的步骤,也是很多功能 BeanFactory 不支持的重要原因。因此 Spring 中大部分功能都是通过后处理器的方式进行扩展的,但是在 BeanFactory 中其实并没有实现后处理器的自动注册,所以在调用的时候如果没有进行手动注册其实是不能使用的。但是在 ApplicationContext 中却添加了自动注册功能,避免了手动注册。
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取所有的BeanPostProcessor处理器名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 使用PriorityOrdered接口保证BeanPostProcessor的执行顺序
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// 使用Ordered接口保证BeanPostProcessor的执行顺序
List<String> orderedPostProcessorNames = new ArrayList<>();
// 无序BeanPostProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// 排序
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
} else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 第1步,注册所有实现PriorityOrdered接口的BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 第2步,注册所有实现Ordered接口的BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 第3步,注册所有无序的BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 第4步,注册所有MergedBeanDefinitionPostProcessor类型的BeanPostProcessor
// 这里并非重复注册,因为在注册时会先移除已经存在的BeanPostProcessor
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 手动添加ApplicationListenerDetector处理器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
2.5 initApplicationEventMulticaster
initApplicationEventMulticaster 方法逻辑比较简单,主要用于初始化应用上下文的事件广播器。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
} else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
- 如果用户自定义了事件广播器,那么直接使用用户自定义的事件广播器。
- 如果用户没有自定义事件广播器,那么使用默认的 SimpleApplicationEventMulticaster。
2.6 registerListeners
�registerListeners 方法主要用来注册事件监听器:
protected void registerListeners() {
// 硬编码方式注册ApplicationListener
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 配置文件注册的监听器处理
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
}
2.7 finishBeanFactoryInitialization
该方法用来完成 BeanFactory 初始化工作,其中包括非延迟加载的 Bean 的初始化工作。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
......
// 不使用TempClassLoader
beanFactory.setTempClassLoader(null);
// 禁止修改当前bean的配置信息,说明注册的bean定义将不被修改或进行任何进一步的处理
beanFactory.freezeConfiguration();
// 实例化所有被标记为non-lazy-init的单例bean
beanFactory.preInstantiateSingletons();
}
ApplicationContext 实现的默认行为就是在启动时将所有单例 bean 提前进行实例化。提前实例化意味着作为初始化过程的一部分,ApplicationContext 实例会创建并配置所有的单例 bean。通常情况下这是一件好事,因为这样在配置中的任何错误就会即刻被发现。其中,非延迟加载的 Bean 的实例化过程是在 BeanFactory 中完成的,preInstantiateSingletons() 方法的代码逻辑具体如下:
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 不是抽象类、是单例类型、不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果bean继承了FactoryBean,执行用户自定义产生实例对象的方法
if (isFactoryBean(beanName)) {
Object bean = getBean("&" + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
......
getBean(beanName);
}
} else {
// getBean方法封装了实例化bean的整个流程
getBean(beanName);
}
}
}
// 触发所有适用bean的初始化后回调
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
......
smartSingleton.afterSingletonsInstantiated();
}
}
}
2.8 finishRefresh
在 Spring 中还提供了 Lifecycle 接口,Lifecycle 中包含 start、stop 方法,实现此接口后 Spring 会保证在启动时调用其 start 方法开始生命周期,并在 Spring 关闭时调用 stop 方法来结束生命周期,通常用来配置一些后台程序,ApplicationContext 的初始化最后正是保证了这一功能的实现。
protected void finishRefresh() {
clearResourceCaches();
// 获取容器中LifecycleProcessor接口
initLifecycleProcessor();
// 调用已注册的LifecycleProcessor接口的onRefresh回调方法
getLifecycleProcessor().onRefresh();
// 当完成 ApplicationContext 初始化时,要通过Spring中的事件发布机制来发出 ContextRefreshedEvent 事件,以保证对应的监听器可以做进一步的逻辑处理
publishEvent(new ContextRefreshedEvent(this));
}
3. 容器事件机制
Spring 的 ApplicationContext 能够发布事件并且允许注册相应的事件监听器,因此,它拥有一套完整的事件发布和监听机制。事件源产生事件(EventObject),通过事件广播器把事件通知给事件监听器(EventListener)。
3.1 Spring 事件类型
1)事件类
目前 Spring 框架本身仅定义了几个事件,ApplicationEvent 的唯一构造函数是 ApplicationEvent(Object source),通过 source 指定事件源,它有两个子类。
ApplicationContextEvent:容器事件,它有 4 个子类,分别表示容器启动、刷新、停止及关闭事件。
- ContextStartedEvent:当 ApplicationContext 启动的时候发布事件。
- ContextRefreshEvent:当 ApplicationContext 容器初始化完成或者被刷新的时候,就会发布该事件。此处的容器初始化指的是所有的 Bean 都被成功装载,后处理(post-processor)Bean 被检测到并且激活,所有单例 Bean 都被预实例化,ApplicationContext 容器已经可以使用。只要上下文没有被关闭,刷新可以被多次触发。
- ContextStoppedEvent:当 ApplicationContext 容器停止的时候发布事件。
- ContextClosedEvent:当 ApplicationContext 关闭的时候发布事件,关闭指的是所有的单例 Bean 都被销毁,关闭后不能重新刷新或重新启动。
RequestHandleEvent:这是一个与 Web 应用相关的事件,当一个 HTTP 请求被处理后,产生该事件。
2)事件监听接口
Spring 的事件监听器都继承自 ApplicationListener 接口。该接口只定义了一个方法:onApplicationEvent(E event),该方法接收 ApplicationEvent 事件对象,在该方法中编写事件的响应处理逻辑。在 Spring 中的,如果一个 Bean 实现了 ApplicationListener 接口,并且已经发布到容器中去,则当 ApplicationContext 通过 publishEvent 方法发布一个 ApplicationEvent 事件时,这个 Bean 就会接到通知。
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
// 指定监听器支持哪种类型的容器事件,即它只会对该类型的事件做出响应
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
// 指定监听器仅对何种事件源对象做出响应
default boolean supportsSourceType(@Nullable Class<?> sourceType) { return true; }
}
GenericApplicationListener 增强了对泛型事件类型的支持,supportsEventType() 方法的参数不再仅限于 ApplicationEvent 子类型,而是采用可解析类型 ResolvableType。
public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
// 指定监听器是否实际支持给定的事件类型,即它只会对该类型的事件做出响应
boolean supportsEventType(ResolvableType eventType);
// 指定监听器仅对何种事件源对象做出响应
default boolean supportsSourceType(@Nullable Class<?> sourceType) { return true; }
}
3)事件广播器
当发生容器事件时,容器将调用事件广播器将事件通知给事件监听器注册表中的事件监听器,事件监听器分别对事件进行响应。Spring 为事件广播器定义了接口,并提供了实现类。
3.2 Spring 事件体系实现原理
Spring 在 ApplicationContext 接口的抽象实现类 AbstractApplicationContext 中完成了事件体系的搭建。该抽象类拥有一个 ApplicationEventMulticaster 成员变量,该变量提供了容器监听器的注册表。AabstractApplicationContext 在 refresh() 这个容器启动方法中通过以下三步搭建了事件的基础设施。
// 5:初始化应用上下文事件广播器
initApplicationEventMulticaster();
// 7:注册事件监听器
registerListeners();
// 9:完成刷新并发布容器刷新事件
finishRefresh();
在 5 处,Spring 初始化事件的广播器。用户可用自定义一个事件广播器,只要实现 ApplicationEventMulticaster 即可,Spring 会通过反射机制将其注册成容器的事件广播器。如果没有找到自定义的,则 Spring 使用 SimpleApplicationEventMulticaster 作为事件广播器。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
} else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
在 7 处,Spring 根据反射机制,从 BeanDefinitionRegistry 中找出所有实现了 ApplicationListener 的 Bean,将它们注册为容器的事件监听器,就是将其添加到事件广播器所提供的事件监听器注册表中。在 9 处,容器启动完成,调用事件发布接口向容器中所有的监听器发布事件。通过 publishEvent() 方法发布一个容器刷新事件,然后根据事件监听器注册表通知监听该事件的监听器。
3.3 使用示例
@Component
public class MailSend implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
@PostConstruct
public void sendMail() {
System.out.println("SendMail:发送邮件");
MailSendEvent event = new MailSendEvent(this.context, "Allen");
context.publishEvent(event);
}
}
Event 定义:
public class MailSendEvent extends ApplicationContextEvent {
private String to;
public MailSendEvent(ApplicationContext source, String to) {
super(source);
this.to = to;
}
@Override
public Object getSource() { return super.getSource(); }
@Override
public String toString() { return super.toString(); }
public String getTo() { return to; }
}
Listener 定义:
@Component
public class MailSendListener implements ApplicationListener<MailSendEvent> {
@Override
public void onApplicationEvent(MailSendEvent event) {
System.out.println("MailSendListener: 向[" + event.getTo() + "]发送一封邮件");
}
}