Spring Aware源碼設(shè)計(jì)示例解析
1. Aware介紹
前一篇講到了BeanPostProcessor的相關(guān)知識(shí),我們知道BeanPostProcessor是對(duì)整個(gè)容器中的Bean做前置和后置增強(qiáng)處理。這樣的實(shí)現(xiàn)方式限制了開發(fā)者只能按照Spring提供的模板,對(duì)Bean做前置和后置的增強(qiáng),這樣雖然已經(jīng)很靈活了,但是如果開發(fā)者想要對(duì)Spring中的Bean做更復(fù)雜的操作或者開發(fā)者想要使用Spring中的BeanFactory、ClassLoader時(shí),這樣的方式明顯就不夠方便了,因此Spring也考慮到了這樣的情況,就提供了另外的方式提升Spring的擴(kuò)展性和靈活性,這種方式就是Aware。
單純說Aware可能不熟悉,但是如果說BeanNameAware、BeanFactoryAware那么是不是就知道這個(gè)Aware到底是何方神圣了。
接下來就說一下Spring提供給開發(fā)者Aware的這個(gè)功能。
Spring中Aware的源碼如下:
public interface Aware {
}
從源碼中可以看到Aware就是一個(gè)簡(jiǎn)單的接口,該接口是一個(gè)無實(shí)現(xiàn)的接口,一般看到這種接口可以都是作為最頂級(jí)的父類接口使用的,使用時(shí)一般都是instanceof判斷是否是頂級(jí)接口類型。
2. Aware類別
在Spring中Aware有幾個(gè)繼承接口,分別是:
- BeanClassLoaderAware
- BeanFactoryAware
- BeanNameAware
2.1 BeanClassLoaderAware
首先是BeanClassLoaderAware接口,從字面意思翻譯就可以大概知道這是一個(gè)關(guān)于Bean的類加載器的接口,因此該接口的功能就聚焦在類加載器上。
BeanClassLoaderAware源碼如下:
public interface BeanClassLoaderAware extends Aware {
//set方法,賦值ClassLoader方法
void setBeanClassLoader(ClassLoader classLoader);
}
從源碼可以看到該接口只提供了一個(gè)setBeanClassLoader方法,該方法就是簡(jiǎn)單的設(shè)置Bean的類加載器的方法,所以從這個(gè)方法中就可以知道BeanClassLoaderAware就單純提供了一個(gè)賦值ClassLoader的方法,這里的接口并不會(huì)指定ClassLoader的接收方,因此接收方需要在實(shí)現(xiàn)該接口的實(shí)現(xiàn)類中指定,然后將ClassLoader賦值給實(shí)現(xiàn)類中的具體常量。
2.2 BeanFactoryAware
BeanFactoryAware接口,看到這個(gè)就立馬想到Spring中的BeanFactory,BeanFactory在Spring中是作為Bean的工廠,那么該接口一定是與BeanFactory相關(guān)的接口。
BeanFactoryAware源碼如下:
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
從源碼中可以看到BeanFactoryAware跟BeanClassLoaderAware相似都只提供了一個(gè)set方法,該接口中只定義了setBeanFactory一個(gè)方法。
該接口中的方法 功能跟BeanClassLoaderAware功能相同,都是賦值,但是該接口賦值的是BeanFactory。
2.3 BeanNameAware
源碼如下:
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
該接口功能同上。(說實(shí)話實(shí)際開發(fā)中沒用到過這個(gè),只用過前兩個(gè),所以我也沒搞懂該類到底可以干啥)。
2.4 ApplicationContextAware
該接口則是一個(gè)特別的接口了,因?yàn)樵摻涌诟叭齻€(gè)繼承Aware的接口不同,ApplicationContextAware并不是spring-bean中提供的接口,而是在spring-context中提供的接口,該接口是從spring-context包中提供的接口,該接口的作用也是跟前三個(gè)類似,并且大部分開發(fā)者用的最多的也是這個(gè)。
源碼如下:
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
@Nullable
String getId();
String getApplicationName();
String getDisplayName();
long getStartupDate();
@Nullable
ApplicationContext getParent();
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
源碼中也是簡(jiǎn)單的賦值操作,但是賦值的對(duì)象是ApplicationContext對(duì)象,對(duì)于這個(gè)對(duì)象使用Spring的一定不陌生。
可以這樣說:ApplicationContext給了開發(fā)者最多的權(quán)限用于操作Bean。
從ApplicationContext源碼中也可以看到該接口繼承了ListableBeanFactory、HierarchicalBeanFactory、ApplicationEventPublisher等其它接口,這樣就將更多的Bean的權(quán)限通過ApplicationContext下放給開發(fā)者?。ㄓ质潜籗pring的高靈活性折服的時(shí)刻)。
3. Aware的使用
@Component
public class MySpringAware implements BeanFactoryAware, BeanClassLoaderAware, ApplicationContextAware, BeanNameAware {
private ApplicationContext applicationContext;
private ListableBeanFactory beanFactory;
private ClassLoader classLoader;
private String beanName;
/**
* 獲取某個(gè)接口下的所有實(shí)現(xiàn)類
*
* @param filter
*/
public void registryFilter(FilterProcessor filter) {
Map<String, MyFilter> beans = beanFactory.getBeansOfType(MyFilter.class);
beans.values().stream().sorted(AnnotationAwareOrderComparator.INSTANCE).forEach(filter::register);
}
/**
* 獲取環(huán)境配置
*
* @return
*/
public Environment getApplicationData() {
return applicationContext.getEnvironment();
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ListableBeanFactory) beanFactory;
}
@Override
public void setBeanName(String s) {
this.beanName = s;
}
}
@Component
public class FilterProcessor {
private final List<MyFilter> filterList = new ArrayList();
public void register(MyFilter filter) {
this.filterList.add(filter);
}
public List<MyFilter> getFilterList() {
return filterList;
}
}
public interface MyFilter {
void doFilter();
}
@Component
@Order(1)
public class MyDemoFilter extends FilterProcessor implements MyFilter{
@Override
public void doFilter() {
System.out.println("執(zhí)行第一個(gè)過濾器MyDemoFilter");
}
}
@Component
@Order(2)
public class MyDemoFilter2 extends FilterProcessor implements MyFilter{
@Override
public void doFilter() {
System.out.println("執(zhí)行第二個(gè)過濾器MyDemoFilter2");
}
}
運(yùn)行結(jié)果:

以上的例子中通過MySpringAware實(shí)現(xiàn)了前文中說到的幾個(gè)Aware,分別使用了其中的BeanFactory和ApplicationContext。這樣在MySpringAware中就可以使用我們定義的常量接收Spring容器中的BeanFactory、ClassLoader、ApplicationContext等功能。
4. Aware的作用
從以上的例子中可以看到,Aware為開發(fā)者提供了插樁式的接口,開發(fā)者只要實(shí)現(xiàn)該接口就可以獲得Spring容器的某些管理權(quán)。
比如BeanClassLoaderAware是獲得對(duì)Bean的類加載器的管理權(quán)。
BeanFactoryAware是活的對(duì)Bean工廠的管理權(quán)。
這樣插樁式的擴(kuò)展可以保證開發(fā)者在使用時(shí)可以獲得Spring中某些功能的管理權(quán),方便開發(fā)者對(duì)Spring的理解和使用,不需要復(fù)雜的實(shí)現(xiàn)就可以獲得Spring內(nèi)部的管理。
5. Aware的調(diào)用
前面說完了Aware的介紹、類別和作用,最后來說實(shí)現(xiàn)Aware相關(guān)接口的實(shí)現(xiàn)類在Spring中是如何被調(diào)用的。
實(shí)現(xiàn)Aware相關(guān)接口的實(shí)現(xiàn)類被調(diào)用的方式與前面講的BeanPostProcessor有一定區(qū)別。
區(qū)別如下:
BeanPostProcessor的調(diào)用:
- 調(diào)用方式:注冊(cè)+讀取注冊(cè)列表(通過register.List和遍歷beanPostProcessorList)
- 調(diào)用時(shí)機(jī):Bean執(zhí)行初始化函數(shù)(invokeInitMethods)之前或者之后
Aware的調(diào)用:
- 調(diào)用方式:通過Bean是否實(shí)現(xiàn)了Aware/BeanClassLoaderAware/BeanFactoryAware,然后調(diào)用相應(yīng)的實(shí)現(xiàn)類的重寫方法
- 調(diào)用時(shí)機(jī):Bean執(zhí)行初始化函數(shù)(invokeInitMethods)之前且beanPostProcessor#before之前
源碼如下:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
//初始化Bean的方法
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
//調(diào)用Bean的Aware重寫接口
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//調(diào)用Bean的Aware重寫接口
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//調(diào)用BeanPostProcessor前置接口
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//調(diào)用Bean的初始化函數(shù)
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//調(diào)用BeanPostProcessor后置接口
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
//調(diào)用Aware的實(shí)現(xiàn)
private void invokeAwareMethods(String beanName, 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);
}
}
}
}
區(qū)別梳理如下:

以AbstractAutowireCapableBeanFactory為主線梳理調(diào)用Aware接口的鏈路如下:
- org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
對(duì)于ApplicationContextAware的調(diào)用鏈路梳理如下:
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
- org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
- org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces
根據(jù)以上的鏈路可以很清晰的看到ApplicationContextAware的調(diào)用實(shí)現(xiàn)。
以上就是Spring Aware源碼設(shè)計(jì)示例解析的詳細(xì)內(nèi)容,更多關(guān)于Spring Aware源碼設(shè)計(jì)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring中ResponseBodyAdvice的使用詳解
這篇文章主要介紹了Spring中ResponseBodyAdvice的使用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
JavaWeb購物車項(xiàng)目開發(fā)實(shí)戰(zhàn)指南
之前沒有接觸過購物車的東東,也不知道購物車應(yīng)該怎么做,所以在查詢了很多資料,總結(jié)一下購物車的功能實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于JavaWeb購物車項(xiàng)目開發(fā)的相關(guān)資料,需要的朋友可以參考下2022-06-06
Java的Hibernate框架數(shù)據(jù)庫操作中鎖的使用和查詢類型
這篇文章主要介紹了Java的Hibernate框架數(shù)據(jù)庫操作中鎖的使用和查詢類型,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2016-01-01
Springcloud中的Nacos?Config服務(wù)配置流程分析
這篇文章主要介紹了Springcloud中的Nacos?Config服務(wù)配置,本文以用戶微服務(wù)為例,進(jìn)行統(tǒng)一的配置,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
Javaweb 500 服務(wù)器內(nèi)部錯(cuò)誤的解決
這篇文章主要介紹了Javaweb 500 服務(wù)器內(nèi)部錯(cuò)誤的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
SpringAop中AspectJ框架的切入點(diǎn)表達(dá)式
這篇文章主要介紹了SpringAop中AspectJ框架的切入點(diǎn)表達(dá)式,AspectJ是一個(gè)基于Java語言的AOP框架,Spring2.0以后新增了對(duì)AspectJ切點(diǎn)表達(dá)式支持,@AspectJ 是AspectJ1.5新增功能,通過JDK5注解技術(shù),允許直接在Bean類中定義切面,需要的朋友可以參考下2023-08-08
springboot整合shiro登錄失敗次數(shù)限制功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了springboot整合shiro-登錄失敗次數(shù)限制功能,實(shí)現(xiàn)此功能如果是防止壞人多次嘗試,破解密碼的情況,所以要限制用戶登錄嘗試次數(shù),需要的朋友可以參考下2018-09-09
Java動(dòng)態(tài)顯示文件上傳進(jìn)度實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Java動(dòng)態(tài)顯示文件上傳進(jìn)度實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
SpringBoot動(dòng)態(tài)數(shù)據(jù)源連接測(cè)試的操作詳解
這篇文章主要介紹了SpringBoot動(dòng)態(tài)數(shù)據(jù)源連接測(cè)試的操作步驟,文中通過代碼示例和圖文結(jié)合的方式給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-03-03
學(xué)習(xí)Java之自定義異常與NullPointerException的處理
有時(shí)候Java自身提供的異常類并不能很好地表達(dá)我們的需求,所以這時(shí)候我們就可以自定義異常,也就是說,我們可以制造出一個(gè)自己的異常類,這樣就可以拋出或捕獲自己的異常了,本文就給大家詳細(xì)講講Java自定義異常與NullPointerException的處理2023-08-08

