Spring Aware 系列接口详解
Spring Aware 系列接口详解一、什么是 Aware 接口Aware 是 Spring 提供的一组回调接口。Bean 实现这些接口后Spring 容器会在创建 Bean 的过程中主动调用对应的方法把容器内部的资源“告知”给 Bean。简单说Aware 接口让 Bean 能够感知到自己所处的容器环境从而获取容器的名称、上下文、环境变量等资源。ComponentpublicclassMyBeanimplementsBeanNameAware{OverridepublicvoidsetBeanName(Stringname){// Spring 回调告知 Bean 自己的名称System.out.println(我的 Bean 名称是name);}}二、为什么需要 Aware 接口普通 Bean 不应该感知 Spring 容器的存在这是 Spring 非侵入性设计的一部分。但有些场景下Bean 确实需要获取容器资源需要知道自己的 Bean 名称用于日志、监控需要获取ApplicationContext来动态获取其他 Bean需要读取Environment中的配置需要加载资源文件需要发布事件Aware 接口提供了一种“受控”的方式让 Bean 在需要时能够获取这些资源而不必强制依赖 Spring 容器。三、常用 Aware 接口一览Aware 接口回调方法获取的资源调用者BeanNameAwaresetBeanName(String)Bean 的名称AbstractAutowireCapableBeanFactoryBeanClassLoaderAwaresetBeanClassLoader(ClassLoader)类加载器AbstractAutowireCapableBeanFactoryBeanFactoryAwaresetBeanFactory(BeanFactory)BeanFactory 实例AbstractAutowireCapableBeanFactoryEnvironmentAwaresetEnvironment(Environment)Environment 实例ApplicationContextAwareProcessorEmbeddedValueResolverAwaresetEmbeddedValueResolver(...)占位符解析器ApplicationContextAwareProcessorResourceLoaderAwaresetResourceLoader(ResourceLoader)资源加载器ApplicationContextAwareProcessorApplicationEventPublisherAwaresetApplicationEventPublisher(...)事件发布器ApplicationContextAwareProcessorMessageSourceAwaresetMessageSource(MessageSource)国际化消息源ApplicationContextAwareProcessorApplicationContextAwaresetApplicationContext(ApplicationContext)ApplicationContext 实例ApplicationContextAwareProcessorServletContextAwaresetServletContext(ServletContext)ServletContextServletContextAwareProcessorServletConfigAwaresetServletConfig(ServletConfig)ServletConfigServletContextAwareProcessorLoadTimeWeaverAwaresetLoadTimeWeaver(LoadTimeWeaver)LTW 织入器LoadTimeWeaverAwareProcessor四、三类 Aware 接口的调用时机Aware 接口的调用分布在 Bean 生命周期的不同阶段主要分为三类。1. BeanNameAware、BeanClassLoaderAware、BeanFactoryAware这三个接口由AbstractAutowireCapableBeanFactory.invokeAwareMethods()调用时机在属性赋值之后、初始化之前。privatevoidinvokeAwareMethods(StringbeanName,Objectbean){if(beaninstanceofAware){if(beaninstanceofBeanNameAware){((BeanNameAware)bean).setBeanName(beanName);}if(beaninstanceofBeanClassLoaderAware){ClassLoaderbclgetBeanClassLoader();if(bcl!null){((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);}}if(beaninstanceofBeanFactoryAware){((BeanFactoryAware)bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}调用顺序BeanNameAware→BeanClassLoaderAware→BeanFactoryAware。2. EnvironmentAware、ResourceLoaderAware 等这些接口由ApplicationContextAwareProcessor调用时机在BeanPostProcessor.postProcessBeforeInitialization阶段也就是初始化前。ApplicationContextAwareProcessor是一个BeanPostProcessor它会在初始化前检查 Bean 是否实现了这些 Aware 接口publicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName){if(!(beaninstanceofEnvironmentAware||beaninstanceofEmbeddedValueResolverAware||beaninstanceofResourceLoaderAware||beaninstanceofApplicationEventPublisherAware||beaninstanceofMessageSourceAware||beaninstanceofApplicationContextAware)){returnbean;}// 依次调用各个 Aware 接口invokeAwareInterfaces(bean);returnbean;}调用顺序EnvironmentAware→EmbeddedValueResolverAware→ResourceLoaderAware→ApplicationEventPublisherAware→MessageSourceAware→ApplicationContextAware。3. ServletContextAware、ServletConfigAware这两个接口由ServletContextAwareProcessor调用也是BeanPostProcessor在 Web 应用中生效。4. 调用时机总结① 实例化 ② 属性赋值 ③ BeanNameAware → BeanClassLoaderAware → BeanFactoryAware ④ 初始化前 EnvironmentAware → EmbeddedValueResolverAware → ResourceLoaderAware → ApplicationEventPublisherAware → MessageSourceAware → ApplicationContextAware → ServletContextAware → ServletConfigAware ⑤ 初始化 ⑥ 初始化后 ⑦ 销毁五、常用接口详解1. BeanNameAware获取自己在容器中的 Bean 名称。常用于日志、监控、注册中心等场景。ComponentpublicclassMyServiceimplementsBeanNameAware{privateStringbeanName;OverridepublicvoidsetBeanName(Stringname){this.beanNamename;}publicvoiddoSomething(){System.out.println(当前 Bean 名称beanName);}}2. BeanFactoryAware获取BeanFactory实例可以动态获取其他 Bean。但日常开发中更推荐用ApplicationContextAware。ComponentpublicclassMyServiceimplementsBeanFactoryAware{privateBeanFactorybeanFactory;OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory){this.beanFactorybeanFactory;}publicvoiddoSomething(){UserDaouserDaobeanFactory.getBean(UserDao.class);userDao.save();}}3. ApplicationContextAware获取ApplicationContext实例可以获取 Bean、发布事件、获取环境等。这是最常用的 Aware 接口。ComponentpublicclassSpringContextHolderimplementsApplicationContextAware{privatestaticApplicationContextcontext;OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext){SpringContextHolder.contextapplicationContext;}publicstaticTTgetBean(ClassTclazz){returncontext.getBean(clazz);}}4. EnvironmentAware获取Environment实例可以读取配置、判断 Profile。ComponentpublicclassMyServiceimplementsEnvironmentAware{privateEnvironmentenvironment;OverridepublicvoidsetEnvironment(Environmentenvironment){this.environmentenvironment;}publicvoiddoSomething(){Stringportenvironment.getProperty(server.port);if(environment.acceptsProfiles(prod)){// 生产环境逻辑}}}5. ResourceLoaderAware获取ResourceLoader用于加载资源文件。ComponentpublicclassMyServiceimplementsResourceLoaderAware{privateResourceLoaderresourceLoader;OverridepublicvoidsetResourceLoader(ResourceLoaderresourceLoader){this.resourceLoaderresourceLoader;}publicvoidloadFile()throwsIOException{ResourceresourceresourceLoader.getResource(classpath:data.txt);try(InputStreamisresource.getInputStream()){// 读取文件}}}6. ApplicationEventPublisherAware获取事件发布器用于发布应用事件。ComponentpublicclassMyServiceimplementsApplicationEventPublisherAware{privateApplicationEventPublisherpublisher;OverridepublicvoidsetApplicationEventPublisher(ApplicationEventPublisherpublisher){this.publisherpublisher;}publicvoiddoSomething(){publisher.publishEvent(newMyEvent(业务完成));}}7. MessageSourceAware获取国际化消息源用于读取多语言消息。ComponentpublicclassMyServiceimplementsMessageSourceAware{privateMessageSourcemessageSource;OverridepublicvoidsetMessageSource(MessageSourcemessageSource){this.messageSourcemessageSource;}publicStringgetMessage(Stringcode,Localelocale){returnmessageSource.getMessage(code,null,locale);}}六、完整示例ComponentpublicclassAwareBeanimplementsBeanNameAware,BeanFactoryAware,EnvironmentAware,ApplicationContextAware,InitializingBean{publicAwareBean(){System.out.println(1. 构造方法);}OverridepublicvoidsetBeanName(Stringname){System.out.println(3.1 BeanNameAware: name);}OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory){System.out.println(3.2 BeanFactoryAware);}OverridepublicvoidsetEnvironment(Environmentenvironment){System.out.println(4.1 EnvironmentAware);}OverridepublicvoidsetApplicationContext(ApplicationContextcontext){System.out.println(4.2 ApplicationContextAware);}OverridepublicvoidafterPropertiesSet(){System.out.println(5. InitializingBean);}}输出1. 构造方法 属性赋值 3.1 BeanNameAware: awareBean 3.2 BeanFactoryAware 4.1 EnvironmentAware 4.2 ApplicationContextAware 5. InitializingBean七、Aware 接口的底层原理Aware 接口的调用分两个阶段分别由不同的组件负责。1. invokeAwareMethodsAbstractAutowireCapableBeanFactory在initializeBean()方法中调用invokeAwareMethods()处理BeanNameAware、BeanClassLoaderAware、BeanFactoryAware。这三个接口被放在AbstractAutowireCapableBeanFactory中直接调用是因为它们不依赖ApplicationContext只需要BeanFactory层面的信息。2. ApplicationContextAwareProcessorApplicationContextAwareProcessor是一个BeanPostProcessor负责处理更高级的 Aware 接口。它在postProcessBeforeInitialization中检查并调用这些接口。classApplicationContextAwareProcessorimplementsBeanPostProcessor{privatefinalConfigurableApplicationContextapplicationContext;OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName){if(beaninstanceofEnvironmentAware){((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());}if(beaninstanceofEmbeddedValueResolverAware){((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(newEmbeddedValueResolver(applicationContext.getBeanFactory()));}if(beaninstanceofResourceLoaderAware){((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);}if(beaninstanceofApplicationEventPublisherAware){((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);}if(beaninstanceofMessageSourceAware){((MessageSourceAware)bean).setMessageSource(this.applicationContext);}if(beaninstanceofApplicationContextAware){((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);}returnbean;}}这个处理器由AbstractApplicationContext.prepareBeanFactory()注册到容器中。3. ServletContextAwareProcessor在 Web 应用中ServletContextAwareProcessor负责处理ServletContextAware和ServletConfigAware同样通过BeanPostProcessor机制实现。八、注意事项1. Aware 接口不是越多越好实现 Aware 接口意味着 Bean 与 Spring 容器产生了耦合。过度使用会让 Bean 难以脱离 Spring 环境使用违背了非侵入性设计原则。只在确实需要时使用。2. 静态字段的坑ApplicationContextAware的setApplicationContext是实例方法不能直接注入静态字段。需要通过实例方法赋值给静态变量ComponentpublicclassSpringContextHolderimplementsApplicationContextAware{privatestaticApplicationContextcontext;OverridepublicvoidsetApplicationContext(ApplicationContextctx){SpringContextHolder.contextctx;// 赋值给静态变量}publicstaticTTgetBean(ClassTclazz){returncontext.getBean(clazz);}}3. 调用顺序同类中多个 Aware 接口的调用顺序是固定的不由接口声明顺序决定。如果需要控制顺序可以在方法中添加日志观察或依赖 Spring 的固定顺序。4. 与 Autowired 的区别Autowired用于注入依赖 Bean而 Aware 接口用于获取容器本身的基础设施。两者用途不同不要混用。九、总结维度核心要点作用让 Bean 感知容器环境获取容器内部资源调用时机属性赋值之后、初始化之前三类接口BeanNameAware等由invokeAwareMethods调用ApplicationContextAware等由ApplicationContextAwareProcessor调用ServletContextAware等由ServletContextAwareProcessor调用常用接口BeanNameAware、BeanFactoryAware、ApplicationContextAware、EnvironmentAware底层实现BeanPostProcessor机制注意事项不要过度使用避免与 Spring 容器耦合过深典型应用获取上下文、读取配置、发布事件、加载资源Aware 接口是 Spring 提供的一种“受控耦合”机制。它让 Bean 在需要时能获取容器资源同时又不强制所有 Bean 都依赖 Spring。理解 Aware 接口的调用时机和底层原理能帮你更好地掌握 Bean 生命周期的细节也能在需要时选择合适的 Aware 接口解决问题。