生活随笔
收集整理的這篇文章主要介紹了
手写简版spring --8--Aware感知容器对象Aware感知容器对象
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、目標(biāo)
目前已實(shí)現(xiàn)的 Spring 框架,在 Bean 操作上能提供出的能力,包括:Bean 對(duì)象的定義和注冊(cè),以及在操作 Bean 對(duì)象過(guò)程中執(zhí)行的,BeanFactoryPostProcessor、BeanPostProcessor、InitializingBean、DisposableBean,以及在 XML 新增的一些配置處理,讓我們可以 Bean 對(duì)象有更強(qiáng)的操作性。那么,如果我們想獲得 Spring 框架提供的 BeanFactory、ApplicationContext、BeanClassLoader等這些能力做一些擴(kuò)展框架的使用時(shí)該怎么操作呢。所以我們本章節(jié)希望在 Spring 框架中提供一種能感知容器操作的接口,如果誰(shuí)實(shí)現(xiàn)了這樣的一個(gè)接口,就可以獲取接口入?yún)⒅械母黝?lèi)能力。
二、設(shè)計(jì)
如果說(shuō)我希望拿到 Spring 框架中一些提供的資源,那么首先需要考慮以一個(gè)什么方式去獲取,之后你定義出來(lái)的獲取方式,在 Spring 框架中該怎么去承接,實(shí)現(xiàn)了這兩項(xiàng)內(nèi)容,就可以擴(kuò)展出你需要的一些屬于 Spring 框架本身的能力了。在關(guān)于 Bean 對(duì)象實(shí)例化階段我們操作過(guò)一些額外定義、屬性、初始化和銷(xiāo)毀的操作,其實(shí)我們?nèi)绻瘾@取 Spring 一些如 BeanFactory、ApplicationContext 時(shí),也可以通過(guò)此類(lèi)方式進(jìn)行實(shí)現(xiàn)。那么我們需要定義一個(gè)標(biāo)記性的接口,這個(gè)接口不需要有方法,它只起到標(biāo)記作用就可以,而具體的功能由繼承此接口的其他功能性接口定義具體方法,最終這個(gè)接口就可以通過(guò) instanceof 進(jìn)行判斷和調(diào)用了。整體設(shè)計(jì)結(jié)構(gòu)如下圖:
定義接口Aware,在Spring框架中它是一種感知標(biāo)記性接口,具體的子類(lèi)定義和實(shí)現(xiàn)能感知容器中的相關(guān)對(duì)象。也就是通過(guò)這個(gè)橋梁,向具體的實(shí)現(xiàn)類(lèi)中提供容器服務(wù)。 繼承 Aware的接口包括:BeanFactoryAware、BeanClassLoaderAware、BeanNameAware和ApplicationContextAware,當(dāng)然在Spring 源碼中還有一些其他關(guān)于注解的,不過(guò)目前我們還是用不到。 在具體的接口實(shí)現(xiàn)過(guò)程中你可以看到,一部分(BeanFactoryAware、BeanClassLoaderAware、BeanNameAware)在factory 的 support 文件夾下,另外 ApplicationContextAware 是在 context 的 support中,這是因?yàn)椴煌膬?nèi)容獲取需要在不同的包下提供。所以,在 AbstractApplicationContext 的具體實(shí)現(xiàn)中會(huì)用到向 beanFactory 添加 BeanPostProcessor 內(nèi)容的 ApplicationContextAwareProcessor 操作,最后由 AbstractAutowireCapableBeanFactory 創(chuàng)建 createBean 時(shí)處理相應(yīng)的調(diào)用操作。關(guān)于applyBeanPostProcessorsBeforeInitialization 已經(jīng)在前面章節(jié)中實(shí)現(xiàn)過(guò),如果忘記可以往前翻翻
三、實(shí)現(xiàn)
工程結(jié)構(gòu)
small
- spring
- step
- 08
└── src├── main│ └── java│ └── cn
. bugstack
. springframework│ ├── beans│ │ ├── factory│ │ │ ├── config│ │ │ │ ├──
AutowireCapableBeanFactory . java│ │ │ │ ├──
BeanDefinition . java│ │ │ │ ├──
BeanFactoryPostProcessor . java│ │ │ │ ├──
BeanPostProcessor . java│ │ │ │ ├──
BeanReference . java│ │ │ │ ├──
ConfigurableBeanFactory . java│ │ │ │ └──
SingletonBeanRegistry . java│ │ │ ├── support│ │ │ │ ├──
AbstractAutowireCapableBeanFactory . java│ │ │ │ ├──
AbstractBeanDefinitionReader . java│ │ │ │ ├──
AbstractBeanFactory . java│ │ │ │ ├──
BeanDefinitionReader . java│ │ │ │ ├──
BeanDefinitionRegistry . java│ │ │ │ ├──
CglibSubclassingInstantiationStrategy . java│ │ │ │ ├──
DefaultListableBeanFactory . java│ │ │ │ ├──
DefaultSingletonBeanRegistry . java│ │ │ │ ├──
DisposableBeanAdapter . java│ │ │ │ ├──
InstantiationStrategy . java│ │ │ │ └──
SimpleInstantiationStrategy . java │ │ │ ├── support│ │ │ │ └──
XmlBeanDefinitionReader . java│ │ │ ├──
Aware . java│ │ │ ├──
BeanClassLoaderAware . java│ │ │ ├──
BeanFactory . java│ │ │ ├──
BeanFactoryAware . java│ │ │ ├──
BeanNameAware . java│ │ │ ├──
ConfigurableListableBeanFactory . java│ │ │ ├──
DisposableBean . java│ │ │ ├──
HierarchicalBeanFactory . java│ │ │ ├──
InitializingBean . java│ │ │ └──
ListableBeanFactory . java│ │ ├──
BeansException . java│ │ ├──
PropertyValue . java│ │ └──
PropertyValues . java │ ├── context│ │ ├── support│ │ │ ├──
AbstractApplicationContext . java │ │ │ ├──
AbstractRefreshableApplicationContext . java │ │ │ ├──
AbstractXmlApplicationContext . java │ │ │ ├──
ApplicationContextAwareProcessor . java │ │ │ └──
ClassPathXmlApplicationContext . java │ │ ├──
ApplicationContext . java │ │ ├──
ApplicationContextAware . java │ │ └──
ConfigurableApplicationContext . java│ ├── core
. io│ │ ├──
ClassPathResource . java │ │ ├──
DefaultResourceLoader . java │ │ ├──
FileSystemResource . java │ │ ├──
Resource . java │ │ ├──
ResourceLoader . java │ │ └──
UrlResource . java│ └── utils│ └──
ClassUtils . java└── test└── java└── cn
. bugstack
. springframework
. test├── bean│ ├──
UserDao . java│ └──
UserService . java└──
ApiTest . java
類(lèi)依賴(lài)關(guān)系
以上整個(gè)類(lèi)關(guān)系就是關(guān)于 Aware 感知的定義和對(duì)容器感知的實(shí)現(xiàn)。 Aware 有四個(gè)繼承的接口,其他這些接口的繼承都是為了繼承一個(gè)標(biāo)記,有了標(biāo)記的存在更方便類(lèi)的操作和具體判斷實(shí)現(xiàn)。 另外由于 ApplicationContext 并不是在 AbstractAutowireCapableBeanFactory 中 createBean 方法下的內(nèi)容,所以需要像容器中注冊(cè) addBeanPostProcessor ,再由 createBean 統(tǒng)一調(diào)用 applyBeanPostProcessorsBeforeInitialization 時(shí)進(jìn)行操作。
定義標(biāo)記接口
public interface Aware {
}
在 Spring 中有特別多類(lèi)似這樣的標(biāo)記接口的設(shè)計(jì)方式,它們的存在就像是一種標(biāo)簽一樣,可以方便統(tǒng)一摘取出屬于此類(lèi)接口的實(shí)現(xiàn)類(lèi),通常會(huì)有 instanceof 一起判斷使用。
容器感知類(lèi)
public interface BeanFactoryAware extends Aware { void setBeanFactory ( BeanFactory beanFactory
) throws BeansException ;
}
Interface to be implemented by beans that wish to be aware of theirowning {@link BeanFactory}. 實(shí)現(xiàn)此接口,既能感知到所屬的 BeanFactory
public interface BeanClassLoaderAware extends Aware { void setBeanClassLoader ( ClassLoader classLoader
) ;
}
Callback that allows a bean to be aware of the bean{@link ClassLoader class loader}; that is, the class loader used by the present beanfactory to load bean classes. 實(shí)現(xiàn)此接口,既能感知到所屬的 ClassLoader
public interface BeanNameAware extends Aware { void setBeanName ( String name
) ;
}
Interface to be implemented by beans that want to be aware of their bean name in a bean factory. 實(shí)現(xiàn)此接口,既能感知到所屬的 BeanName
3.4 ApplicationContextAware
public interface ApplicationContextAware extends Aware { void setApplicationContext ( ApplicationContext applicationContext
) throws BeansException ;
}
Interface to be implemented by any object that wishes to be notified of the {@link ApplicationContext} that it runs in. 實(shí)現(xiàn)此接口,既能感知到所屬的ApplicationContext
包裝處理器(ApplicationContextAwareProcessor)
public class ApplicationContextAwareProcessor implements BeanPostProcessor { private final ApplicationContext applicationContext
; public ApplicationContextAwareProcessor ( ApplicationContext applicationContext
) { this . applicationContext
= applicationContext
; } @Override public Object postProcessBeforeInitialization ( Object bean
, String beanName
) throws BeansException { if ( bean
instanceof ApplicationContextAware ) { ( ( ApplicationContextAware ) bean
) . setApplicationContext ( applicationContext
) ; } return bean
; } @Override public Object postProcessAfterInitialization ( Object bean
, String beanName
) throws BeansException { return bean
; }
}
由于 ApplicationContext 的獲取并不能直接在創(chuàng)建 Bean 時(shí)候就可以拿到,所以需要在 refresh 操作時(shí),把ApplicationContext 寫(xiě)入到一個(gè)包裝的 BeanPostProcessor 中去,由AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization方法調(diào)用。
注冊(cè) BeanPostProcessor
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { @Override public void refresh ( ) throws BeansException { refreshBeanFactory ( ) ; ConfigurableListableBeanFactory beanFactory
= getBeanFactory ( ) ; beanFactory
. addBeanPostProcessor ( new ApplicationContextAwareProcessor ( this ) ) ; invokeBeanFactoryPostProcessors ( beanFactory
) ; registerBeanPostProcessors ( beanFactory
) ; beanFactory
. preInstantiateSingletons ( ) ; }
}
refresh() 方法就是整個(gè) Spring 容器的操作過(guò)程,與上一章節(jié)對(duì)比,本次新增加了關(guān)于 addBeanPostProcessor 的操作。添加 ApplicationContextAwareProcessor,讓繼承自 ApplicationContextAware 的 Bean 對(duì)象都能感知所屬的 ApplicationContext。
感知調(diào)用操作
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { private InstantiationStrategy instantiationStrategy
= new CglibSubclassingInstantiationStrategy ( ) ; @Override protected Object createBean ( String beanName
, BeanDefinition beanDefinition
, Object [ ] args
) throws BeansException { Object bean
= null ; try { bean
= createBeanInstance ( beanDefinition
, beanName
, args
) ; applyPropertyValues ( beanName
, bean
, beanDefinition
) ; bean
= initializeBean ( beanName
, bean
, beanDefinition
) ; } catch ( Exception e
) { throw new BeansException ( "Instantiation of bean failed" , e
) ; } registerDisposableBeanIfNecessary ( beanName
, bean
, beanDefinition
) ; addSingleton ( beanName
, bean
) ; return bean
; } private Object initializeBean ( String beanName
, Object bean
, BeanDefinition beanDefinition
) { if ( bean
instanceof Aware ) { if ( bean
instanceof BeanFactoryAware ) { ( ( BeanFactoryAware ) bean
) . setBeanFactory ( this ) ; } if ( bean
instanceof BeanClassLoaderAware ) { ( ( BeanClassLoaderAware ) bean
) . setBeanClassLoader ( getBeanClassLoader ( ) ) ; } if ( bean
instanceof BeanNameAware ) { ( ( BeanNameAware ) bean
) . setBeanName ( beanName
) ; } } Object wrappedBean
= applyBeanPostProcessorsBeforeInitialization ( bean
, beanName
) ; try { invokeInitMethods ( beanName
, wrappedBean
, beanDefinition
) ; } catch ( Exception e
) { throw new BeansException ( "Invocation of init method of bean[" + beanName
+ "] failed" , e
) ; } wrappedBean
= applyBeanPostProcessorsAfterInitialization ( bean
, beanName
) ; return wrappedBean
; } @Override public Object applyBeanPostProcessorsBeforeInitialization ( Object existingBean
, String beanName
) throws BeansException { Object result
= existingBean
; for ( BeanPostProcessor processor
: getBeanPostProcessors ( ) ) { Object current
= processor
. postProcessBeforeInitialization ( result
, beanName
) ; if ( null == current
) return result
; result
= current
; } return result
; } @Override public Object applyBeanPostProcessorsAfterInitialization ( Object existingBean
, String beanName
) throws BeansException { Object result
= existingBean
; for ( BeanPostProcessor processor
: getBeanPostProcessors ( ) ) { Object current
= processor
. postProcessAfterInitialization ( result
, beanName
) ; if ( null == current
) return result
; result
= current
; } return result
; }
}
這里我們?nèi)サ袅艘恍╊?lèi)的內(nèi)容,只保留關(guān)于本次 Aware 感知接口的操作。首先在 initializeBean 中,通過(guò)判斷 bean instanceof Aware,調(diào)用了三個(gè)接口方法, BeanFactoryAware.setBeanFactory(this) BeanClassLoaderAware.setBeanClassLoader(getBeanClassLoader())、 BeanNameAware.setBeanName(beanName), 這樣就能通知到已經(jīng)實(shí)現(xiàn)了此接口的類(lèi)。另外我們還向 BeanPostProcessor 中添加了ApplicationContextAwareProcessor,此時(shí)在這個(gè)方法中也會(huì)被調(diào)用到具體的類(lèi)實(shí)現(xiàn),得到一個(gè)ApplicationContex 屬性。
四、測(cè)試
事先準(zhǔn)備
public class UserDao { private static Map < String , String > hashMap
= new HashMap < > ( ) ; public void initDataMethod ( ) { System . out
. println ( "執(zhí)行:init-method" ) ; hashMap
. put ( "10001" , "小傅哥" ) ; hashMap
. put ( "10002" , "八杯水" ) ; hashMap
. put ( "10003" , "阿毛" ) ; } public void destroyDataMethod ( ) { System . out
. println ( "執(zhí)行:destroy-method" ) ; hashMap
. clear ( ) ; } public String queryUserName ( String uId
) { return hashMap
. get ( uId
) ; }
}
public class UserService implements BeanNameAware , BeanClassLoaderAware , ApplicationContextAware , BeanFactoryAware { private ApplicationContext applicationContext
; private BeanFactory beanFactory
; private String uId
; private String company
; private String location
; private UserDao userDao
; @Override public void setBeanFactory ( BeanFactory beanFactory
) throws BeansException { this . beanFactory
= beanFactory
; } @Override public void setApplicationContext ( ApplicationContext applicationContext
) throws BeansException { this . applicationContext
= applicationContext
; } @Override public void setBeanName ( String name
) { System . out
. println ( "Bean Name is:" + name
) ; } @Override public void setBeanClassLoader ( ClassLoader classLoader
) { System . out
. println ( "ClassLoader:" + classLoader
) ; }
}
UserDao 本次并沒(méi)有什么改變,還是提供了關(guān)于初始化的方法,并在 Spring.xml 中提供init-method、destroy-method 配置信息。 UserService 新增加,BeanNameAware,BeanClassLoaderAware, ApplicationContextAware,BeanFactoryAware,四個(gè)感知的實(shí)現(xiàn)類(lèi),并在類(lèi)中實(shí)現(xiàn)相應(yīng)的接口方法。
配置文件 基礎(chǔ)配置,無(wú)BeanFactoryPostProcessor、BeanPostProcessor,實(shí)現(xiàn)類(lèi)
<?xml version="1.0" encoding="UTF-8"?>
< beans> < bean id = " userDao" class = " cn.bugstack.springframework.test.bean.UserDao" init-method = " initDataMethod" destroy-method = " destroyDataMethod" /> < bean id = " userService" class = " cn.bugstack.springframework.test.bean.UserService" > < property name = " uId" value = " 10001" /> < property name = " company" value = " 騰訊" /> < property name = " location" value = " 深圳" /> < property name = " userDao" ref = " userDao" /> </ bean>
</ beans>
五、總結(jié)
目前關(guān)于 Spring 框架的實(shí)現(xiàn)中,某些功能點(diǎn)已經(jīng)越來(lái)趨向于完整,尤其是 Bean 對(duì)象的生命周期,已經(jīng)有了很多的體現(xiàn)。整體總結(jié)如圖
本章節(jié)關(guān)于 Aware 的感知接口的四個(gè)繼承接口 BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware 的實(shí)現(xiàn),又?jǐn)U展了 Spring 的功能。如果你有做過(guò)關(guān)于 Spring中間件的開(kāi)發(fā)那么一定會(huì)大量用到這些類(lèi),現(xiàn)在你不只是用過(guò),而且還知道他們都是什么時(shí)候觸達(dá)的,在以后想排查類(lèi)的實(shí)例化順序也可以有一個(gè)清晰的思路了。 每一章節(jié)內(nèi)容的實(shí)現(xiàn)都是在以設(shè)計(jì)模式為核心的結(jié)構(gòu)上填充各項(xiàng)模塊的功能,單純的操作編寫(xiě)代碼并不會(huì)有太多收獲,一定是要理解為什么這么設(shè)計(jì),這么設(shè)計(jì)的好處是什么,怎么就那么多接口和抽象類(lèi)的應(yīng)用,這些才是Spring 框架學(xué)習(xí)的核心所在。
總結(jié)
以上是生活随笔 為你收集整理的手写简版spring --8--Aware感知容器对象Aware感知容器对象 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。