一、Aware接口用来做什么
在使用Spring时,如果我们想在Bean中使用Spring底层的资源,例如:ApplicationContext
, StringValueResolver
等时,该如何得到呢? 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
,EmbeddedValueResolverAware
, BeanNameAware
为例,先感性了解一下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的样子: