Spring中的Aware接口详细解析

 更新时间:2023年12月20日 08:32:49   作者:城堡斗士  
这篇文章主要介绍了Spring中的Aware接口详细解析,Aware是一个具有标识作用的超级接口,具体实现是有子接口去决定的,但是子接口至少要有一个带一个参数的且返回是空的方法,需要的朋友可以参考下

Aware接口介绍

Aware是一个具有标识作用的超级接口,具体实现是有子接口去决定的,但是子接口至少要有一个带一个参数的且返回是空的方法。实现该接口的bean是具有被spring 容器通知的能力的,而被通知的方式就是通过回调。也就是说:直接或间接实现了这个接口的类,都具有被spring容器通知的能力。

Aware翻译过来是adj. 知道的,明白的,察觉到的,意识到的,所以这些接口从字面意思应该是能感知到所有Aware前面的含义。 比如实现了ApplicationContextAware接口的类,能够获取到ApplicationContext,实现了BeanFactoryAware接口的类,能够获取到BeanFactory对象。

package org.springframework.beans.factory;
/**
 * A marker superinterface indicating that a bean is eligible to be notified by the
 * Spring container of a particular framework object through a callback-style method.
 * The actual method signature is determined by individual subinterfaces but should
 * typically consist of just one void-returning method that accepts a single argument.
 *
 * <p>Note that merely implementing {@link Aware} provides no default functionality.
 * Rather, processing must be done explicitly, for example in a
 * {@link org.springframework.beans.factory.config.BeanPostProcessor}.
 * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 * for an example of processing specific {@code *Aware} interface callbacks.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 */
public interface Aware {
}

Aware常用子接口如下:

org.springframework.context.ApplicationContextAware
org.springframework.beans.factory.BeanFactoryAware
org.springframework.beans.factory.BeanClassLoaderAware
org.springframework.beans.factory.BeanNameAware
org.springframework.context.EnvironmentAware
org.springframework.context.ResourceLoaderAware
org.springframework.context.annotation.ImportAware

1.ApplicationContextAware

实现该接口的类可以获取spring容器上下文信息 ApplicationContext , ApplicationContextAware接口源码如下:

public interface ApplicationContextAware extends Aware {
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

下面demo可通过类的静态方法调用来获取applicationContext上下文信息:

@Component
public class ApplicationContextStaticProvider implements ApplicationContextAware {
	private static ApplicationContext context;
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		context = applicationContext;
	}
	public static ApplicationContext getApplicationContext() {
		return context;
	}
	/**
	 * 通过beanName获取Bean
	 *
	 * @param beanName
	 * @return
	 */
	public static Object getBean(String beanName) {
		return getApplicationContext().getBean(beanName);
	}
	/**
	 * 通过class获取bean
	 *
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	public static <T> T getBean(Class<T> clazz) {
		return getApplicationContext().getBean(clazz);
	}
	/**
	 * 通过name,以及Clazz返回指定的bean
	 *
	 * @param beanName
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	public static <T> T getBean(String beanName, Class<T> clazz) {
		return getApplicationContext().getBean(beanName, clazz);
	}
}
@Service
public class DemoBean {
	public void test(String str){
		System.out.println(str);
	}
}
public class AnnotationConfigApplicationContextTests {
	@Test
	public void scanAndRefreshTestAware() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.scan("org.springframework.context.annotation7");
		context.refresh();
		DemoBean demoBean= (DemoBean) ApplicationContextStaticProvider.getBean("demoBean");
		demoBean.test("test applicationContextAware");
	}
}

调用过程分析

Spring在初始化Bean时,如何回调ApplicationContextAware接口setApplicationContext方法呢?

我们来看如下调用顺序:

1.AbstractApplicationContext#refresh() ;

2.AbstractApplicationContext#prepareBeanFactory() —> beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

3.AbstractApplicationContext#finishBeanFactoryInitialization();

4.DefaultListableBeanFactory#preInstantiateSingletons()—>getBean(beanName);

5.AbstractAutowireCapableBeanFactory#doCreateBean();

6.AbstractAutowireCapableBeanFactory#initializeBean();填充bean属性后,初始化bean。

7.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization()

8.执行ApplicationContextAwareProcessor.postProcessBeforeInitialization()

9.ApplicationContextAwareProcessor#invokeAwareInterfaces()

private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			// 最终调用ApplicationContextAware.setApplicationContext()方法
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

第一步: AbstractApplicationContext#refresh()

第二步:给bean工厂配置ApplicationContextAware回调处理 AbstractApplicationContext#prepareBeanFactory() —> beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

第三步:初始化bean的过程(实例化(一般调用构造方法实例化bean)、属性注入、bean初始化),属性注入后,bean初始化前,调用ApplicationContextAware实现类setApplicationContext()方法

2.BeanFactoryAware

Spring Ioc 中最顶层的父接口就是BeanFactory。实现这个BeanFactoryAware接口的子类可以获取spring容器的BeanFactory 对象,进而可以动态的去操作 要在spring容器中注入的bean。

ApplicationContext接口是BeanFactory的子接口,所以继承ApplicationContextAware的实现类拿到ApplicationContext 对象比实现BeanFactoryAware接口拿到BeanFactory 对象 可以获取更多的信息。

BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能提前发现一些Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean(单例)。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。BeanFacotry延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身时检验,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用 ApplicationContext。应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

3.BeanNameAware

这个接口的含义就是让实现类知道自己在spring容器中定义的beanName是什么,实际开发一般没啥用。

4.BeanClassLoaderAware

获取spring 容器的类加载器ClassLoader 对象; org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

正常使用的是: Thread.currentThread().getContextClassLoader();

5.EnvironmentAware

实现这个接口的类能获取Environmet对象,进而可以各种系统变量信息,也可以设置 变量的优先级别等等。 通过Environment 对象可以获取spring boot框架中的application.properties中定义的变量值。

6.ResourceLoaderAware

获取资源加载器ResourceLoader 对象,可以获得外部资源文件。

到此这篇关于Spring中的Aware接口详细解析的文章就介绍到这了,更多相关Spring的Aware接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java9中新增的Collector收集器

    Java9中新增的Collector收集器

    这篇文章主要介绍了Java9中新增的Collector收集器,Collector作为收集器,简单来说就是将数据或元素收集到一起,并且flatMapping与收集器结合使用,通过提供智能元素集合进行分组。下文相关介绍需要的小伙伴可以参考一下
    2022-06-06
  • Java解析微信获取手机号信息的示例步骤

    Java解析微信获取手机号信息的示例步骤

    在微信中,用户手机号的获取通常是通过微信小程序的getPhoneNumber接口来实现的,下面通过一个基于Java的示例,展示了如何接收并解密从微信小程序传递过来的加密手机号信息,感兴趣的朋友一起看看吧
    2024-06-06
  • Spring AOP失效的常见场景分析

    Spring AOP失效的常见场景分析

    Spring的AOP(面向切面编程)是一种强大的技术,用于在应用程序中实现横切关注点的模块化,虽然Spring的AOP在大多数情况下都是有效的,但在某些场景下可能会失效,下面来分析Spring AOP失效的常见场景,需要的朋友可以参考下
    2024-01-01
  • 关于maven使用过程中无法导入依赖的一些总结

    关于maven使用过程中无法导入依赖的一些总结

    这篇文章主要介绍了关于maven使用过程中无法导入依赖的一些总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 解决Swagger2返回map复杂结构不能解析的问题

    解决Swagger2返回map复杂结构不能解析的问题

    这篇文章主要介绍了解决Swagger2返回map复杂结构不能解析的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • SpringBoot 过滤器 Filter使用实例详解

    SpringBoot 过滤器 Filter使用实例详解

    这篇文章主要为大家介绍了SpringBoot 过滤器Filter使用实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • 详解Java中字典树(Trie树)的图解与实现

    详解Java中字典树(Trie树)的图解与实现

    Trie又称为前缀树或字典树,是一种有序树,它是一种专门用来处理串匹配的数据结构。本文将利用图解详细讲解Trie树的实现,需要的可以参考一下
    2022-05-05
  • java模拟实现斗地主发牌小程序

    java模拟实现斗地主发牌小程序

    这篇文章主要为大家详细介绍了java模拟实现斗地主发牌小程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • 详解SpringCloud的负载均衡

    详解SpringCloud的负载均衡

    这篇文章主要介绍了SpringCloud的负载均衡的相关资料,帮助大家更好的理解和学习使用SpringCloud,感兴趣的朋友可以了解下
    2021-03-03
  • Spring定时任务中数据未持久化的深度排查和解决指南

    Spring定时任务中数据未持久化的深度排查和解决指南

    在Spring Boot应用中,开发人员常通过@Scheduled定时任务实现日志缓存批量写入数据库的功能,然而,即使代码执行无报错、事务已提交,数据库表却始终未保存任何数据,所以本文给大家介绍了Spring定时任务中数据未持久化的深度排查指南,需要的朋友可以参考下
    2025-10-10

最新评论