Spring Aware源碼設(shè)計示例解析
1. Aware介紹
前一篇講到了BeanPostProcessor的相關(guān)知識,我們知道BeanPostProcessor是對整個容器中的Bean做前置和后置增強處理。這樣的實現(xiàn)方式限制了開發(fā)者只能按照Spring提供的模板,對Bean做前置和后置的增強,這樣雖然已經(jīng)很靈活了,但是如果開發(fā)者想要對Spring中的Bean做更復(fù)雜的操作或者開發(fā)者想要使用Spring中的BeanFactory、ClassLoader時,這樣的方式明顯就不夠方便了,因此Spring也考慮到了這樣的情況,就提供了另外的方式提升Spring的擴展性和靈活性,這種方式就是Aware。
單純說Aware可能不熟悉,但是如果說BeanNameAware、BeanFactoryAware那么是不是就知道這個Aware到底是何方神圣了。
接下來就說一下Spring提供給開發(fā)者Aware的這個功能。
Spring中Aware的源碼如下:
public interface Aware { }
從源碼中可以看到Aware就是一個簡單的接口,該接口是一個無實現(xiàn)的接口,一般看到這種接口可以都是作為最頂級的父類接口使用的,使用時一般都是instanceof判斷是否是頂級接口類型。
2. Aware類別
在Spring中Aware有幾個繼承接口,分別是:
- BeanClassLoaderAware
- BeanFactoryAware
- BeanNameAware
2.1 BeanClassLoaderAware
首先是BeanClassLoaderAware接口,從字面意思翻譯就可以大概知道這是一個關(guān)于Bean的類加載器的接口,因此該接口的功能就聚焦在類加載器上。
BeanClassLoaderAware源碼如下:
public interface BeanClassLoaderAware extends Aware { //set方法,賦值ClassLoader方法 void setBeanClassLoader(ClassLoader classLoader); }
從源碼可以看到該接口只提供了一個setBeanClassLoader方法,該方法就是簡單的設(shè)置Bean的類加載器的方法,所以從這個方法中就可以知道BeanClassLoaderAware就單純提供了一個賦值ClassLoader的方法,這里的接口并不會指定ClassLoader的接收方,因此接收方需要在實現(xiàn)該接口的實現(xiàn)類中指定,然后將ClassLoader賦值給實現(xiàn)類中的具體常量。
2.2 BeanFactoryAware
BeanFactoryAware接口,看到這個就立馬想到Spring中的BeanFactory,BeanFactory在Spring中是作為Bean的工廠,那么該接口一定是與BeanFactory相關(guān)的接口。
BeanFactoryAware源碼如下:
public interface BeanFactoryAware extends Aware { void setBeanFactory(BeanFactory beanFactory) throws BeansException; }
從源碼中可以看到BeanFactoryAware跟BeanClassLoaderAware相似都只提供了一個set方法,該接口中只定義了setBeanFactory一個方法。
該接口中的方法 功能跟BeanClassLoaderAware功能相同,都是賦值,但是該接口賦值的是BeanFactory。
2.3 BeanNameAware
源碼如下:
public interface BeanNameAware extends Aware { void setBeanName(String name); }
該接口功能同上。(說實話實際開發(fā)中沒用到過這個,只用過前兩個,所以我也沒搞懂該類到底可以干啥)。
2.4 ApplicationContextAware
該接口則是一個特別的接口了,因為該接口跟前三個繼承Aware的接口不同,ApplicationContextAware并不是spring-bean中提供的接口,而是在spring-context中提供的接口,該接口是從spring-context包中提供的接口,該接口的作用也是跟前三個類似,并且大部分開發(fā)者用的最多的也是這個。
源碼如下:
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; }
源碼中也是簡單的賦值操作,但是賦值的對象是ApplicationContext對象,對于這個對象使用Spring的一定不陌生。
可以這樣說:ApplicationContext給了開發(fā)者最多的權(quán)限用于操作Bean。
從ApplicationContext源碼中也可以看到該接口繼承了ListableBeanFactory、HierarchicalBeanFactory、ApplicationEventPublisher等其它接口,這樣就將更多的Bean的權(quán)限通過ApplicationContext下放給開發(fā)者?。ㄓ质潜籗pring的高靈活性折服的時刻)。
3. Aware的使用
@Component public class MySpringAware implements BeanFactoryAware, BeanClassLoaderAware, ApplicationContextAware, BeanNameAware { private ApplicationContext applicationContext; private ListableBeanFactory beanFactory; private ClassLoader classLoader; private String beanName; /** * 獲取某個接口下的所有實現(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í)行第一個過濾器MyDemoFilter"); } } @Component @Order(2) public class MyDemoFilter2 extends FilterProcessor implements MyFilter{ @Override public void doFilter() { System.out.println("執(zhí)行第二個過濾器MyDemoFilter2"); } }
運行結(jié)果:
以上的例子中通過MySpringAware實現(xiàn)了前文中說到的幾個Aware,分別使用了其中的BeanFactory和ApplicationContext。這樣在MySpringAware中就可以使用我們定義的常量接收Spring容器中的BeanFactory、ClassLoader、ApplicationContext等功能。
4. Aware的作用
從以上的例子中可以看到,Aware為開發(fā)者提供了插樁式的接口,開發(fā)者只要實現(xiàn)該接口就可以獲得Spring容器的某些管理權(quán)。
比如BeanClassLoaderAware是獲得對Bean的類加載器的管理權(quán)。
BeanFactoryAware是活的對Bean工廠的管理權(quán)。
這樣插樁式的擴展可以保證開發(fā)者在使用時可以獲得Spring中某些功能的管理權(quán),方便開發(fā)者對Spring的理解和使用,不需要復(fù)雜的實現(xiàn)就可以獲得Spring內(nèi)部的管理。
5. Aware的調(diào)用
前面說完了Aware的介紹、類別和作用,最后來說實現(xiàn)Aware相關(guān)接口的實現(xiàn)類在Spring中是如何被調(diào)用的。
實現(xiàn)Aware相關(guān)接口的實現(xiàn)類被調(diào)用的方式與前面講的BeanPostProcessor有一定區(qū)別。
區(qū)別如下:
BeanPostProcessor的調(diào)用:
- 調(diào)用方式:注冊+讀取注冊列表(通過register.List和遍歷beanPostProcessorList)
- 調(diào)用時機:Bean執(zhí)行初始化函數(shù)(invokeInitMethods)之前或者之后
Aware的調(diào)用:
- 調(diào)用方式:通過Bean是否實現(xiàn)了Aware/BeanClassLoaderAware/BeanFactoryAware,然后調(diào)用相應(yīng)的實現(xiàn)類的重寫方法
- 調(diào)用時機: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的實現(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
對于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)用實現(xiàn)。
以上就是Spring Aware源碼設(shè)計示例解析的詳細內(nèi)容,更多關(guān)于Spring Aware源碼設(shè)計的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
輕松理解Java面試和開發(fā)中的IoC(控制反轉(zhuǎn))
在Java開發(fā)中,IoC意 味著將你設(shè)計好的類交給系統(tǒng)去控制,而不是在你的類內(nèi)部控制。這稱為控制反轉(zhuǎn)。下文給大家介紹Java面試和開發(fā)中的IoC(控制反轉(zhuǎn))知識,需要的朋友參考下吧2017-07-07Mybatis執(zhí)行SQL時多了一個limit的問題及解決方法
這篇文章主要介紹了Mybatis執(zhí)行SQL時多了一個limit的問題及解決方法,Mybatis攔截器方法識別到配置中參數(shù)supportMethodsArguments 為ture時會分頁處理,本文結(jié)合示例代碼給大家講解的非常詳細,需要的朋友可以參考下2022-10-10spring-cloud-gateway動態(tài)路由的實現(xiàn)方法
這篇文章主要介紹了spring-cloud-gateway動態(tài)路由的實現(xiàn)方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01關(guān)于Lambda表達式的方法引用和構(gòu)造器引用簡的單示例
這篇文章主要介紹了關(guān)于Lambda表達式的方法引用和構(gòu)造器引用簡的單示例,方法引用與構(gòu)造器引用可以使?Lambda?表達式的代碼塊更加簡潔<BR>,需要的朋友可以參考下2023-04-04