Spring 源碼測試實例
一個注解配置類,在com包里有一個User接口,兩個實現了User接口的方法(提示:從本章開始,建議讀者邊看邊實操)
測試類,筆者將以AnnotationConfigApplicationContext
這個注解類作為入口對源碼進行深度分析
Spring 源碼分析
進入筆者將以AnnotationConfigApplicationContext的構造方法
注意細節AnnotationConfigApplicationContext繼承了GenericApplicationContext
所以會優先執行GenericApplicationContext的默認構造器,并且會創造一個叫DefaultListableBeanFactory的這么個類,
這個類分量很大,是Spring的核心類,我們點開DefaultListableBeanFactory這個類,
我們一步一步向上跟蹤會發現它實現了BeanFactory,所以這就我們一直說的Bean工廠、Bean工廠,實際上Bean工廠也就是在這個時候就創建了,當然這個類還要其他重要的功能,筆者暫時放一放,咱們繼續往下走,執行完父類的構造器后,現在開始執行自己的構造器了
public AnnotationConfigApplicationContext() {
//這個reader顧名思義是一個讀取器,而且十分重要,稍后會說明為什么重要
this.reader = new AnnotatedBeanDefinitionReader(this);
//這個scanner說實話沒有什么卵用,因為在spring內部自己new了一個掃描器,而不是用的這個對象,而這個類是交給程序員手動獲取的,基本用不到
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
如上圖所示:AnnotationConfigApplicationContext構造器創建了一個讀取器,一個掃描器,而這個scanner為什么由上述注釋所寫的后期我們在掃描的時候證明。進入this.reader=new AnnotatedBeanDefinitionReader(this); 這行代碼調入然后構造器相互調用最終調用這個構造器
進入AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
里面又是委托模式,繼續滲入registerAnnotationConfigProcessors(registry, null);
最終進入核心方法registerAnnotationConfigProcessors()這個方法大概就做了兩件事情,獲取之前創建的DefaultListableBeanFactory,然后往里面裝一些工具組件,包含排序組件、轉換器組件、以及4個特別特別重要的后置處理器。分別是
1、ConfigurationClassPostProcessor
2、AutowiredAnnotationBeanPostProcessor
3、CommonAnnotationBeanPostProcessor
4、EventListenerMethodProcessor
在registerAnnotationConfigProcessors()涉及到Spring后置處理器和BeanDefinition,下面會進行簡要分析
Spring后置處理器
什么是后置處理器,筆者這里對Spring其中一個頂層的后置處理器進行詳細說明
看了上面的注釋,讀者可能還是比較懵逼,我們在實踐一下
這里并沒有對Spring Bean流程詳細介紹,只是對整體流程描述了大概。如果還是不明白我們在后面會詳細說明后置處理器的作用。
BeanDefinition
在think in java的作者提出,一切皆為對象,一切皆可抽象,而BeanDefinition正是Spring抽象設計的精髓,回到上文筆者強調Bean和對象不是同一個概念,Spring認為僅僅是java自帶的對象是不能滿足于我所需求的,就好比單例、Lazy等一些特性無法滿足,所以Spring定義一個BeanDefinition作為對象的抽象,來實現對象的抽象,(當然BeanDefinition的分量很高,筆者在后面會更詳細的介紹它具體的作用)明白這點后我們回到代碼:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//從注冊器獲取beanFactory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
//這里是判斷beanFactory有沒有排序的工具
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
//這里是判斷beanFactory有沒有轉換器
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
//之后你會看到很多BeanDefinitionHolder,這個BeanDefinitionHolder其實沒什么作用,就是一個
//封裝了BeanDefinition的map,而BeanDefinition是對spring將要實例化對象的一個緩存,
//類似于對象的class,只是功能比class更豐富
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//重點來了,這里涉及到了一個概念叫BeanFactoryPostProcessor,詳細看接口
//registerPostProcessor這個方法就是將RootBeanDefinition放到工廠的map對象去
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//下面是注冊五個類,但有一個類會被忽略,所以總共只注冊了五個類
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
這里其實就是獲取前面創建的工廠,然后向工廠裝一些組件,目的就是初始化工廠,然后再為工廠創建Spring自定義的后置處理器作為BeanDefinition存起來,然后返回,這是我們的this已經執行完畢,回到這個圖。
咱們再看一遍注釋,相信讀者大致能理解
我們再看register方法->this.reader.register(componentClasses);->registerBean(componentClass);->doRegisterBean(beanClass, null, null, null);
<T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//這里可以看到使用AnnotatedGenericBeanDefinition去創建的 后面會通過這個類的父接口去做一些判斷
//此外在這個創建注解BD的時候就對內部的元注解進行初始化,自己有標識了注解
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
//獲取作用域元數據
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//這里是對Config配置類進行注解信息的設置,Lazy,Primary,DependsOn等等
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//將bd注冊到我們的BeanFactory去
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
其實我們可以看到核心代碼就是最下面一句, BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);將我們的配置類或普通類注冊到BeanDefinitionMap集合里。而前面只是做一些判斷,比如是不是Lazy,Primary,DependsOn,有沒有Supplier等
深度分析Spring核心方法refresh()
refresh()目錄
//這個方法沒什么用,里面都是一些系統環境設置
prepareRefresh();
// 這里只是將beanFactory拿出來
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 對beanFactory添加一些處理器,并設置一些屬性
prepareBeanFactory(beanFactory);
// 空方法
postProcessBeanFactory(beanFactory);
// 這里是執行實現了BeanFactoryPostProcessor這個接口的子類
// 重點就是spring自己的一個類
// 秒掃出要實例化的類,放進工廠的beanDef里面,這里只是放的bd并不是真正的實例化對象invokeBeanFactoryPostProcessors(beanFactory);
//注冊BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this
context.initMessageSource();
// 創建ApplicationEventMulticaster這么一個類initApplicationEventMulticaster();
//空方法
onRefresh();
// 注冊監聽器
registerListeners();
//完成對bean的創建finishBeanFactoryInitialization(beanFactory);
// publish corresponding event.
finishRefresh();
我們可以看到Spring在refresh方法里面做了很多很多的事情,我們逐步分析:
prepareRefresh():這個方法并不用太關注,這是Spring記錄一些系統日期、日志之類的,我們直接跳過。
obtainFreshBeanFactory():這個方法只是將創建的工廠拿出來給后續的方法作為參數利用
prepareBeanFactory():
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 這里是對beanFactory設置一些工具類,后面用到再說,先跳過
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加一個ApplicationContextAwareProcessor后置處理器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//設置一些需要忽略的類,避免重復,這里就是避免從面部傳進這些class影響Spring內部操作
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
看這句代碼,beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));、進入ApplicationContextAwareProcessor 找到下面代碼
可以看到里面有大量的回調接口。如果沒搞明白我們寫了例子
可以看出,我們可以通過回調拿到Spring內部的對象,這里可以結合再一個實例,單例對象的屬性注入原型對象,就需要這種方式解決,而這個對象那里來的呢,咱們回到源碼:
//解決依賴注入來源問題
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 注冊一個用來銷毀Bean的后置處理器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
這里就是Spring內部注冊的對象,這里涉及到一個數據源的問題,我們會在依賴注入的環節單獨詳細說明筆者暫且可以認為這些對象沒有經過Spring的生命周期,但可以提供依賴注入。
postProcessBeanFactory()
空殼方法,這里猜測是Spring為自己預留的拓展功能。接下來的方法較為重要,筆者打算單獨開一章節詳細分析
本小節總結:
1、創建一個工廠 this.beanFactory = new DefaultListableBeanFactory();
2、創建一個讀取器 this.reader = new AnnotatedBeanDefinitionReader(this);
3、對beanFactory添加一些組件工具,添加4個后置處理器
4、通過之前創建的讀取器把傳進來的類轉換為BeanDefinition注冊到工廠里。
5、Spring在自己內部設置了一些數據源信息比如ApplicationContext、Resourse等
6、添加了一個ApplicationContextAwareProcessor后置處理器提供Aware回調
7、忽略一些Spring內部關鍵的類,防止外部修改或影響了Spring內部的核心類