Aware接口

一、Aware接口用来做什么

在使用Spring时,如果我们想在Bean中使用Spring底层的资源,例如:ApplicationContextStringValueResolver等时,该如何得到呢? Aware接口就提供给了我们这个功能.

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 {

}

二、一个例子

Spring框架中的资源太多了,这里就以获取ApplicationContextAware,EmbeddedValueResolverAwareBeanNameAware为例,先感性了解一下XxxAware的作用,然后再去看看它是怎么实现的.

1. ApplicationContextAware接口

需要去实现setApplicationContext方法来完成对ApplicationContext的获取(已经通过形参的方式提供了).

在对Bean进行初始化之前,会通过回调的方式调用setApplicationContext方法.

public interface ApplicationContextAware extends Aware {

	/**
	 * Set the ApplicationContext that this object runs in.
	 * Normally this call will be used to initialize the object.
	 * <p>Invoked after population of normal bean properties but before an init callback such
	*/
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

2. EmbeddedValueResolverAware接口

需要去实现setEmbeddedValueResolver方法来完成对StringValueResolver的获取(已经通过形参的方式提供了).

在对Bean进行初始化之前,会通过回调的方式调用setEmbeddedValueResolver方法.

public interface EmbeddedValueResolverAware extends Aware {

	/**
	 * Set the StringValueResolver to use for resolving embedded definition values.
	 */
	void setEmbeddedValueResolver(StringValueResolver resolver);

}

3. BeanNameAware接口

在对Bean注册之后,会调用该方法. name为这个bean在factory中的名字.

public interface BeanNameAware extends Aware {

	/**
	 * Set the name of the bean in the bean factory that created this bean.
	 * <p>Invoked after population of normal bean properties but before an
	 */
	void setBeanName(String name);

}

对上面三个接口的使用如下:

package czf.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;

/**
 * @author czf
 * @Date 2020/4/27 8:52 下午
 */
@Component()
public class TryAware implements ApplicationContextAware, EmbeddedValueResolverAware, BeanNameAware {
	private ApplicationContext applicationContext;
	private StringValueResolver stringValueResolver;

	@Override
	public void setBeanName(String name) {
		System.out.println("注入了"+name);
	}


	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		// 进行set
		this.applicationContext = applicationContext;
		System.out.println("设置完毕applicationContext");
	}


	@Override
	public void setEmbeddedValueResolver(StringValueResolver resolver) {
		// 进行set
		this.stringValueResolver = resolver;
		// 对其使用
		System.out.println("解析:"+resolver.resolveStringValue("用户名字:${os.masterName}, 年龄:#{20+2}, 系统名称:${os.name}"));
	}
}

三、通过XxxAwareProcessor回调实现

每一个XxxAware都会有对应的一个XxxAwareProcessor来对其进行回调,而XxxAwareProcessor实现了BeanPostProcessor接口,会在Bean的初始化前后来完成对XxxAware的回调. 下面以ApplicationContextAware接口为例子.


class ApplicationContextAwareProcessor implements BeanPostProcessor {

	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初始化之前调用这个方法!!!
	 * 在这个方法中,调用invokeAwareInterfaces(bean)
	 *
	 * 然后在invokeAwareInterfaces(bean)中,通过判断bean是什么类型的,
	 * 来对Aware进行强转XxxAware,并调用其接口方法.
	 *
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return
	 * @throws BeansException
	 */
	@Override
	@Nullable
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		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();
		}

		// 权限检查
		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			// 在这里~~~~~~~~~~~
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	/**
	 * 回调实现逻辑:
	 * 		通过判断Aware是什么类型,然后将Aware强转成对应类型并进行方法的调用
	 * @param bean
	 */
	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);
			}
			//spring帮你set一个applicationContext对象
			//所以当我们自己的一个对象实现了ApplicationContextAware对象只需要提供setter就能得到applicationContext对象
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}

}

更清楚的调用链:

上图倒数第二步中,遍历Processor的样子:
 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值