为什么实现了ApplicationContextAware接口可以获取当前的上下文对象ApplicationContext

  • 接着上篇文章所讲述如何获取当前Sring上下文容器的方法,本篇要说的是为什么实现一个接口就能获取到ApplicationContext对象

ApplicationContextAware接口

public interface ApplicationContextAware extends Aware {
	/**
	 * XXXXXX
	 */
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
  • 从源码上看这个接口内,只定义了一个setApplicationContext方法,该接口的功能就很明确了,就只用于帮助开发者获取ApplicationContext对象。
  • 但是问题出来了,为什么可以获取这个对象?我们自己定义一个接口怎么就没办法让接口具有这种能力。接下来我们就去看一下Sring是怎么实现的

BeanPostProcessor接口

public interface BeanPostProcessor {
	/**
	 * 在Bean初始化之前的行为
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
	
	/**
	 * 在Bean初始化完毕以后会执行
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

ApplicationContextAwareProcessor

  • ApplicationContextAwareProcessor实现了BeanPostProcessor接口,所以重点关注重写的postProcessBeforeInitialization、postProcessAfterInitialization方法做了哪些事情,让我们可以获得ApplicationContext对象。
class ApplicationContextAwareProcessor implements BeanPostProcessor {
	/**
	 * 继承了ApplicationContext
	 */
	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;
	
	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}

	/**
	 * 这里是Bean初始化在Sring容器时,会先调用该方法处理
	 */
	@Override
	@Nullable
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;
		
		// partOne  ystem.getSecurityManager() != null 表示这里只能是一些系统默认指定的bean进入该判断,我们拓展的方法是无法进入该判断的
		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}
		
		// partOne 正常来说不会进入,所以该判断也不会进入
		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			// 这里才是真正关注的地方
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	/**
	 * 重点:上面初始化方法会调用此方法
	 * 该方法的作用:从方法命名上可以大概推测出,这里是处理实例化感知接口(Aware接口的实现类的处理)
	 */
	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的实现类,如果是,则是true
			if (bean instanceof ApplicationContextAware) {
				// 将上下文对象放入其中
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}
}
  • 根据上面代码的注释基本上就能清楚实现ApplicationContextAware接口,为什么可以拿到ApplicationContext对象了。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值