Aware接口
一、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的作用,然后再去看看它是怎么實現(xiàn)的.
1. ApplicationContextAware接口
需要去實現(xiàn)setApplicationContext方法來完成對ApplicationContext的獲取(已經(jīng)通過形參的方式提供了).
在對Bean進(jìn)行初始化之前,會通過回調(diào)的方式調(diào)用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接口
需要去實現(xiàn)setEmbeddedValueResolver方法來完成對StringValueResolver的獲取(已經(jīng)通過形參的方式提供了).
在對Bean進(jìn)行初始化之前,會通過回調(diào)的方式調(diào)用setEmbeddedValueResolver方法.
public interface EmbeddedValueResolverAware extends Aware {/*** Set the StringValueResolver to use for resolving embedded definition values.*/void setEmbeddedValueResolver(StringValueResolver resolver);}3. BeanNameAware接口
在對Bean注冊之后,會調(diào)用該方法.?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;@Overridepublic void setBeanName(String name) {System.out.println("注入了"+name);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {// 進(jìn)行setthis.applicationContext = applicationContext;System.out.println("設(shè)置完畢applicationContext");}@Overridepublic void setEmbeddedValueResolver(StringValueResolver resolver) {// 進(jìn)行setthis.stringValueResolver = resolver;// 對其使用System.out.println("解析:"+resolver.resolveStringValue("用戶名字:${os.masterName}, 年齡:#{20+2}, 系統(tǒng)名稱:${os.name}"));} }三、通過XxxAwareProcessor回調(diào)實現(xiàn)
每一個XxxAware都會有對應(yīng)的一個XxxAwareProcessor來對其進(jìn)行回調(diào),而XxxAwareProcessor實現(xiàn)了BeanPostProcessor接口,會在Bean的初始化前后來完成對XxxAware的回調(diào). 下面以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初始化之前調(diào)用這個方法!!!* 在這個方法中,調(diào)用invokeAwareInterfaces(bean)** 然后在invokeAwareInterfaces(bean)中,通過判斷bean是什么類型的,* 來對Aware進(jìn)行強(qiáng)轉(zhuǎn)XxxAware,并調(diào)用其接口方法.** @param bean the new bean instance* @param beanName the name of the bean* @return* @throws BeansException*/@Override@Nullablepublic 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();}// 權(quán)限檢查if (acc != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareInterfaces(bean);return null;}, acc);}else {// 在這里~~~~~~~~~~~invokeAwareInterfaces(bean);}return bean;}/*** 回調(diào)實現(xiàn)邏輯:* 通過判斷Aware是什么類型,然后將Aware強(qiáng)轉(zhuǎn)成對應(yīng)類型并進(jìn)行方法的調(diào)用* @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對象//所以當(dāng)我們自己的一個對象實現(xiàn)了ApplicationContextAware對象只需要提供setter就能得到applicationContext對象if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}}}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {return bean;}}更清楚的調(diào)用鏈:
上圖倒數(shù)第二步中,遍歷Processor的樣子:
?
?
總結(jié)
- 上一篇: Spring系列之BeanPostPro
- 下一篇: Spring源码(1)