在看源码的时候,经过层层追踪,发现有这么一个接口 Aware,这是一个空接口,空接口又称标记接口。标记接口的作用是实现该接口的类都被标记具有某项功能。(标记接口的介绍:java中的空接口实现它有什么用?)
那么扩展Aware接口的类都具有什么功能呢?
Aware 是 Spring框架 3.1 版本 beans 包中的一个接口,源码如下:
一个超级标记接口,指示一个Bean有资格通过回调式方法被Spring容器通知某个特定框架对象。具体的方法签名由各个子接口确定,但通常应该只包含一个接受单个参数且返回void的方法。
这段话不好懂,没关系,继续往下看。
Aware 的子接口,每个过一遍。
1、ApplicationContextAware 接口中有一个方法:
void setApplicationContext(ApplicationContext applicationContext)
实现该接口的 Bean 可以在初始化时获取到 ApplicationContext 对象,从而可以与 Spring 容器进行交互,例如获取其他 Bean、访问环境变量、注册监听器等。
2、BeanFactoryAware 接口中有一个方法:
void setBeanFactory(BeanFactory beanFactory)
实现该接口的 Bean 可以在初始化时获取到 BeanFactory 对象,从而可以与 Spring 容器进行交互,例如获取其他 Bean、访问环境变量、注册监听器等。和上面的 ApplicationContextAware 作用一样。
3、ApplicationEventPublisherAware 接口中有一个方法:
void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)
实现该接口的 Bean 可以在初始化时获取到 applicationEventPublisher 对象,发布应用程序事件,或将自定义事件发布到 Spring 应用程序上下文中,从而实现事件驱动的编程模型。
4、BeanClassLoaderAware 接口中有一个方法:
void setBeanClassLoader(ClassLoader classLoader)
实现该接口的 Bean 可以在初始化时获取到 classLoader 类加载器,从而可以动态加载类、资源文件等操作。对于一些需要动态加载类或资源的情况非常有用,例如在某些框架或库中需要根据运行时的情况加载特定类或配置文件时。
5、BeanNameAware 接口中有一个方法:
void setBeanName(String name)
实现该接口的 Bean 可以在初始化时获取到自己在 Spring 容器中的名字。
6、EmbeddedValueResolverAware 接口中有一个方法:
void setEmbeddedValueResolver(StringValueResolver resolver)
实现该接口的 Bean 可以在初始化时获取解析嵌入值的解析器 StringValueResolver 对象,使用它来解析配置文件中的占位符,获取真实的值并进行相应的处理。这样可以使 Bean 在初始化时获取到配置文件中的动态值,从而实现更灵活的配置和处理逻辑。
嵌入值是指在配置文件中使用 ${…} 格式的占位符,Spring 容器会在加载配置文件时将这些占位符替换为相应的值。
7、EnvironmentAware 接口中有一个方法:
void setEnvironment(Environment environment)
实现该接口的 Bean 可以在初始化时获取 Spring 的 Environment 环境对象,从而获取配置文件中的属性值、系统属性、环境变量等,Bean 可以根据不同的环境进行相应的逻辑处理,例如根据配置文件中的属性值决定 Bean 的行为,或者根据环境变量来动态调整 Bean 的配置等,使 Bean 在不同的环境下具有更灵活的适应性和可配置性。
8、ImportAware 接口中有一个方法:
void setImportMetadata(AnnotationMetadata importMetadata)
实现该接口的 Bean 可以在初始化时获取到导入该 Bean 的类信息 AnnotationMetadata 对象,包括导入类的名称、注解信息等,并根据需要进行相应的处理,例如根据导入类的信息来动态调整 Bean 的配置或行为。这样可以使 Bean 在被导入时具有更多的灵活性和可定制性。
9、LoadTimeWeaverAware 接口中有一个方法:
void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver)
实现该接口的 Bean 可以在初始化时获取加载时织入器LoadTimeWeaver 对象,从而可以在类加载时进行一些额外的操作,例如织入切面、增强类等。加载时织入是一种在类加载时动态织入增强的技术,典型的应用是在使用 AspectJ 进行编程时。
10、MessageSourceAware 接口中有一个方法:
void setMessageSource(MessageSource messageSource)
实现该接口的 Bean 可以在初始化时获取到消息源 MessageSource 对象,设置相应语言的消息文本,从而可以实现国际化的消息处理。
11、NotificationPublisherAware 接口中有一个方法:
void setNotificationPublisher(NotificationPublisher notificationPublisher)
实现该接口的 Bean 可以在初始化时获取通知发布器NotificationPublisher 对象,发布通知或事件,以便其他组件可以监听到并采取相应的行动,从而实现更灵活和松耦合的组件之间的通信和协作。
12、ResourceLoaderAware 接口中有一个方法:
void setResourceLoader(ResourceLoader resourceLoader)
实现该接口的 Bean 可以在初始化时获取资源加载器ResourceLoader对象,用于加载各种资源,例如文件、URL、类路径等,实现更灵活的资源管理和处理。
13、SchedulerContextAware 接口中有一个方法:
void setSchedulerContext(SchedulerContext schedulerContext)
实现该接口的 Bean 可以在初始化时获取调度器上下文SchedulerContext 对象,提供与调度器相关的信息和操作,通常用于管理任务调度和执行。例如添加、删除或修改调度任务,更灵活地与调度器交互,实现定时任务的管理和控制。
14、ServletConfigAware 接口中有一个方法:
void setServletConfig(ServletConfig servletConfig)
实现该接口的 Bean 可以在初始化时获取到 Servlet 配置信息,包含了 Servlet 的初始化参数,可以在运行时被访问和利用。
15、ServletContextAware 接口中有一个方法:
void setServletContext(ServletContext servletContext)
实现该接口的 Bean 可以在初始化时获取 Servlet 上下文ServletContext 对象,访问 Web 应用程序的上下文信息,与 Web 应用程序的环境进行交互,实现更灵活的 Web 开发和配置,例如获取 Web 应用程序的初始化参数、获取资源文件的真实路径、访问 ServletContext 中的属性等。
把 Aware 的15个子接口过了一遍,可以发现3个规律:
第一,每个子接口只有一个set方法;
第二,实现子接口的 bean 可以在 bean 初始化时获取到 set 方法中的对象。
第三,获取到 set 方法中的对象后,就可以根据这个对象做一些业务逻辑上的操作。
通过这些子接口,大致可以推出 Aware 接口的作用。
Aware 翻译成中文是知道的、意识到的,是个形容词。知道的、意识到的啥呢,得有个名词吧,子接口给出了我们想要的答案。
ApplicationContextAware 接口是想知道 ApplicationContext 容器对象。
BeanFactoryAware 接口是想知道 BeanFactory对象。
ApplicationEventPublisherAware接口是想知道 ApplicationEventPublisher对象。
其他子接口以此类推,最后我们可以得出 Aware 标记接口的作用:在Spring应用程序中的Bean初始化时,可以访问Spring容器的特定服务或资源。
了解了 Aware和其子接口的作用,我们就可以在需要的时候,扩展Aware或它的子接口。
上面我们没有举例子,只是简单说明作用,其中一个比较常见的场景就是在容器外获取容器中的bean。
参考:
SpringBoot项目启动成功后,bean实例化成功,但是用的时候注入失败,我们应该怎么解决?
领取专属 10元无门槛券
私享最新 技术干货