引子你用 MyBatis 时Mapper接口能被直接注入——它既没有实现类也没法newSpring 是怎么造出代理的答案藏在FactoryBean。本篇上半场讲FactoryBean下半场讲 Spring 的事件机制观察者模式它是组件解耦的利器。一句话结论FactoryBean是一个生产 Bean 的工厂 Bean你getBean(beanName)拿到的是它getObject()返回的对象而非FactoryBean本身要拿工厂本身加前缀。SmartFactoryBean增加了isEagerInit()控制是否预实例化。事件机制由ApplicationEventPublisher即ApplicationContextApplicationEventMulticasterApplicationListener构成发布即广播天然解耦。前置知识FactoryBeanT接口三个方法getObject()返回产品、getObjectType()、isSingleton()。事件四角色事件ApplicationEvent、监听器ApplicationListener、发布者ApplicationEventPublisherApplicationContext、广播器ApplicationEventMulticaster第 5 篇第 8 步初始化。上半场FactoryBean一、为什么需要 FactoryBean有些对象的创建很复杂如SqlSessionFactory、各类代理对象不适合在 XML/注解里直接new。FactoryBean把如何创建这个对象封装进工厂容器只管调用它的getObject()。publicinterfaceFactoryBeanT{TgetObject()throwsException;// 返回真正要注册的对象Class?getObjectType();// 对象类型用于类型匹配defaultbooleanisSingleton(){returntrue;}// 是否单例}二、getBean 如何区分 FactoryBean 与它的产品关键点当BeanDefinition指向一个FactoryBean时getBean(beanName)返回的是产品加前缀才返回工厂本身。// AbstractBeanFactory.getObjectForBeanInstance精简protectedObjectgetObjectForBeanInstance(ObjectbeanInstance,Stringname,StringbeanName,RootBeanDefinitionmbd){// name 以 开头 → 要的就是 FactoryBean 本身if(BeanFactoryUtils.isFactoryDereference(name)){returnbeanInstance;// 直接返回 FactoryBean}// 不是 且确实是 FactoryBean → 取它的产品if(beanInstanceinstanceofFactoryBean){ObjectobjectgetObjectFromFactoryBean((FactoryBean?)beanInstance,beanName,mbd);returnobject;// 返回 getObject() 的结果}returnbeanInstance;}⚠️易错点getBean(userMapper)拿到的是 Mapper 代理对象getBean(userMapper)拿到的才是MapperFactoryBean本身。MyBatis 的Mapper正是通过MapperFactoryBeanFactoryBean在getObject()里生成代理。三、SmartFactoryBeanSmartFactoryBean在FactoryBean基础上增加isEagerInit()返回true时即使不是单例也会被提前初始化在finishBeanFactoryInitialization阶段随饿加载一起创建。isPrototype()标识返回原型对象。场景写法拿到什么取产品ctx.getBean(beanName)FactoryBean.getObject()的返回值取工厂ctx.getBean(beanName)FactoryBean实例本身下半场Spring 事件机制四、四角色与发布流程context.publishEvent(event) └─ getApplicationEventMulticaster().multicastEvent(event) └─ 遍历匹配的 ApplicationListener └─ 线程池 or 当前线程 → listener.onApplicationEvent(event)// 发布AbstractApplicationContextpublicvoidpublishEvent(ApplicationEventevent){getApplicationEventMulticaster().multicastEvent(event);// 广播}// 广播SimpleApplicationEventMulticasterpublicvoidmulticastEvent(ApplicationEventevent){for(ApplicationListener?listener:getApplicationListeners(event)){ExecutorexecutorgetTaskExecutor();// 配置了线程池则异步if(executor!null)executor.execute(()-invokeListener(listener,event));elseinvokeListener(listener,event);// 默认同步同线程}}五、监听器两种写法实现ApplicationListenerE接口泛型指定事件类型。任意 Bean 的方法上加EventListener由EventListenerMethodProcessor——一个BeanFactoryPostProcessor——解析并包装成ApplicationListenerMethodAdapter。内置事件触发时机ContextRefreshedEvent容器刷新完成第 5 篇finishRefreshContextStartedEventstart()调用ContextStoppedEventstop()调用ContextClosedEventclose()调用六、组合图 下方为 FactoryBean 获取流程 事件发布时序图。七、常见误区误区正解getBean(x)拿到 FactoryBean 本身否拿到的是getObject()产品加才拿工厂EventListener方法就是监听器它被包装成ApplicationListenerMethodAdapter不是直接实现接口事件默认异步默认同步同线程需配置TaskExecutor才异步原型 Bean 的 FactoryBean 产品每次 new由isSingleton()决定默认单例八、面试题自测FactoryBean的作用是什么为什么 MyBatis 的 Mapper 适合用它如何拿到FactoryBean本身getBean默认返回什么Spring 事件机制的四个角色分别是什么EventListener的原理是什么它和ApplicationListener接口有何关系事件如何变成异步发布九、Debug 小技巧在getObjectForBeanInstance第一行打断电观察name是否以开头决定返回工厂还是产品。在SimpleApplicationEventMulticaster.multicastEvent打断电看getTaskExecutor()为null同步还是线程池异步。自定义一个ApplicationEvent和EventListener方法发布后单步进invokeListener确认监听器被命中。下篇预告IoC 核心到此讲完。下一篇进入AOP 阶段第 11 篇EnableAspectJAutoProxy到底做了什么自动代理创建器如何被注册。如果这篇对你有帮助欢迎点赞 · 收藏 · 关注三连支持。Spring 源码系列共 30 篇由浅入深持续更新中。有疑问或想深挖的源码点评论区告诉我下篇见。