生活随笔
收集整理的這篇文章主要介紹了
手写简版spring --8--Aware感知容器对象Aware感知容器对象
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、目標
目前已實現的 Spring 框架,在 Bean 操作上能提供出的能力,包括:Bean 對象的定義和注冊,以及在操作 Bean 對象過程中執行的,BeanFactoryPostProcessor、BeanPostProcessor、InitializingBean、DisposableBean,以及在 XML 新增的一些配置處理,讓我們可以 Bean 對象有更強的操作性。那么,如果我們想獲得 Spring 框架提供的 BeanFactory、ApplicationContext、BeanClassLoader等這些能力做一些擴展框架的使用時該怎么操作呢。所以我們本章節希望在 Spring 框架中提供一種能感知容器操作的接口,如果誰實現了這樣的一個接口,就可以獲取接口入參中的各類能力。
二、設計
如果說我希望拿到 Spring 框架中一些提供的資源,那么首先需要考慮以一個什么方式去獲取,之后你定義出來的獲取方式,在 Spring 框架中該怎么去承接,實現了這兩項內容,就可以擴展出你需要的一些屬于 Spring 框架本身的能力了。在關于 Bean 對象實例化階段我們操作過一些額外定義、屬性、初始化和銷毀的操作,其實我們如果像獲取 Spring 一些如 BeanFactory、ApplicationContext 時,也可以通過此類方式進行實現。那么我們需要定義一個標記性的接口,這個接口不需要有方法,它只起到標記作用就可以,而具體的功能由繼承此接口的其他功能性接口定義具體方法,最終這個接口就可以通過 instanceof 進行判斷和調用了。整體設計結構如下圖:
定義接口Aware,在Spring框架中它是一種感知標記性接口,具體的子類定義和實現能感知容器中的相關對象。也就是通過這個橋梁,向具體的實現類中提供容器服務。 繼承 Aware的接口包括:BeanFactoryAware、BeanClassLoaderAware、BeanNameAware和ApplicationContextAware,當然在Spring 源碼中還有一些其他關于注解的,不過目前我們還是用不到。 在具體的接口實現過程中你可以看到,一部分(BeanFactoryAware、BeanClassLoaderAware、BeanNameAware)在factory 的 support 文件夾下,另外 ApplicationContextAware 是在 context 的 support中,這是因為不同的內容獲取需要在不同的包下提供。所以,在 AbstractApplicationContext 的具體實現中會用到向 beanFactory 添加 BeanPostProcessor 內容的 ApplicationContextAwareProcessor 操作,最后由 AbstractAutowireCapableBeanFactory 創建 createBean 時處理相應的調用操作。關于applyBeanPostProcessorsBeforeInitialization 已經在前面章節中實現過,如果忘記可以往前翻翻
三、實現
工程結構
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
類依賴關系
以上整個類關系就是關于 Aware 感知的定義和對容器感知的實現。 Aware 有四個繼承的接口,其他這些接口的繼承都是為了繼承一個標記,有了標記的存在更方便類的操作和具體判斷實現。 另外由于 ApplicationContext 并不是在 AbstractAutowireCapableBeanFactory 中 createBean 方法下的內容,所以需要像容器中注冊 addBeanPostProcessor ,再由 createBean 統一調用 applyBeanPostProcessorsBeforeInitialization 時進行操作。
定義標記接口
public interface Aware {
}
在 Spring 中有特別多類似這樣的標記接口的設計方式,它們的存在就像是一種標簽一樣,可以方便統一摘取出屬于此類接口的實現類,通常會有 instanceof 一起判斷使用。
容器感知類
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}. 實現此接口,既能感知到所屬的 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. 實現此接口,既能感知到所屬的 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. 實現此接口,既能感知到所屬的 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. 實現此接口,既能感知到所屬的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 的獲取并不能直接在創建 Bean 時候就可以拿到,所以需要在 refresh 操作時,把ApplicationContext 寫入到一個包裝的 BeanPostProcessor 中去,由AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization方法調用。
注冊 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() 方法就是整個 Spring 容器的操作過程,與上一章節對比,本次新增加了關于 addBeanPostProcessor 的操作。添加 ApplicationContextAwareProcessor,讓繼承自 ApplicationContextAware 的 Bean 對象都能感知所屬的 ApplicationContext。
感知調用操作
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
; }
}
這里我們去掉了一些類的內容,只保留關于本次 Aware 感知接口的操作。首先在 initializeBean 中,通過判斷 bean instanceof Aware,調用了三個接口方法, BeanFactoryAware.setBeanFactory(this) BeanClassLoaderAware.setBeanClassLoader(getBeanClassLoader())、 BeanNameAware.setBeanName(beanName), 這樣就能通知到已經實現了此接口的類。另外我們還向 BeanPostProcessor 中添加了ApplicationContextAwareProcessor,此時在這個方法中也會被調用到具體的類實現,得到一個ApplicationContex 屬性。
四、測試
事先準備
public class UserDao { private static Map < String , String > hashMap
= new HashMap < > ( ) ; public void initDataMethod ( ) { System . out
. println ( "執行:init-method" ) ; hashMap
. put ( "10001" , "小傅哥" ) ; hashMap
. put ( "10002" , "八杯水" ) ; hashMap
. put ( "10003" , "阿毛" ) ; } public void destroyDataMethod ( ) { System . out
. println ( "執行: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 本次并沒有什么改變,還是提供了關于初始化的方法,并在 Spring.xml 中提供init-method、destroy-method 配置信息。 UserService 新增加,BeanNameAware,BeanClassLoaderAware, ApplicationContextAware,BeanFactoryAware,四個感知的實現類,并在類中實現相應的接口方法。
配置文件 基礎配置,無BeanFactoryPostProcessor、BeanPostProcessor,實現類
<?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>
五、總結
目前關于 Spring 框架的實現中,某些功能點已經越來趨向于完整,尤其是 Bean 對象的生命周期,已經有了很多的體現。整體總結如圖
本章節關于 Aware 的感知接口的四個繼承接口 BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware 的實現,又擴展了 Spring 的功能。如果你有做過關于 Spring中間件的開發那么一定會大量用到這些類,現在你不只是用過,而且還知道他們都是什么時候觸達的,在以后想排查類的實例化順序也可以有一個清晰的思路了。 每一章節內容的實現都是在以設計模式為核心的結構上填充各項模塊的功能,單純的操作編寫代碼并不會有太多收獲,一定是要理解為什么這么設計,這么設計的好處是什么,怎么就那么多接口和抽象類的應用,這些才是Spring 框架學習的核心所在。
總結
以上是生活随笔 為你收集整理的手写简版spring --8--Aware感知容器对象Aware感知容器对象 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。