javascript
Spring源码(1)
準備spring環境:
@org.junit.Test public void test01(){//把spring所有環境準備好// 1.準備好DefaultListableBeanFactory// 實例化一個bdReader和一個ScannerAnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext();//把一個class轉成bd,最后put到mapapplicationContext.register(AppConfig.class);//初始化spring的環境applicationContext.refresh();}構造方法
進入AnnotationConfigApplicationContext類:
1.調用AnnotationConfigApplicationContext()構造方法的時候,會先調用父類構造器new出一個工廠DefaultListableBeanFactory。
//new一個工廠DefaultListableBeanFactory public GenericApplicationContext() {this.beanFactory = new DefaultListableBeanFactory(); }2.初始化一個bean的讀取器AnnotatedBeanDefinitionReader和一個掃描器ClassPathBeanDefinitionScanner。
?reader可以讀取被加了注解的類,scanner可以掃描所有加了注解的bean。
public AnnotationConfigApplicationContext() {/*** 父類的構造方法* 創建一個讀取注解的BeanDefinition讀取器* 什么是bean定義?BeanDefinition*///reader能夠讀取被加了注解的類 this是一個注冊器,用來將BeanDefinition轉為工廠中的mapthis.reader = new AnnotatedBeanDefinitionReader(this);//可以用來掃描包或者類,繼而轉換成bd//但是實際上我們掃描包工作不是scanner這個對象來完成的//是spring自己new的一個ClassPathBeanDefinitionScanner//這里的scanner僅僅是為了程序員能夠在外部調用AnnotationConfigApplicationContext對象的scan方法this.scanner = new ClassPathBeanDefinitionScanner(this); }3.進入this.reader = new AnnotatedBeanDefinitionReader(this)方法,一直到:?
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)?3.1? 該方法中首先調用了unwrapDefaultListableBeanFactory()方法,這樣獲取到工廠。當前的工廠是一個空的工廠,給工廠設置依賴比較器(應該是這樣翻譯的吧),設置處理延遲加載的功能。
?????? 3.2? 設置BeanDefinitionHolder(裝的是beanName+BeanDefinition,基本沒啥作用,只是為了傳參方便,本來傳beanName和BeanDefinition,現在傳BeanDefinitionHolder就可以)。org.springframework.context.annotation.internalConfigurationAnnotationProcessor
?????? 3.3? 將ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,EventListenerMethodProcessor?,DefaultEventListenerFactory 6個
spring的內置的類轉為6個RootBeanDefinition,然后注冊器BeanDefinitionRegistry將這些個類注冊進工廠,最后這個RootBeanDefinition轉換成beanName+BeanDefinition的方式放入BeanDefinitionHolder。
該registerAnnotationConfigProcessors方法的目的就是將ConfigurationClassPostProcessor類以及其他內置類裝入BeanDefinitionHolder,然后返回BeanDefinitionHolder。
接下來回到2。然后是研究this.scanner = new ClassPathBeanDefinitionScanner(this)。這個scanner的作用基本很小,如果在外部比如調用applicationContext.scan("")方法才會利用到。否則一切的掃描注冊和它沒有啥關系。
這樣,AnnotationConfigApplicationContext()構造完成。
注冊
接下來就是注冊。進入applicationContext.register(AppConfig.class)方法。
4.進入doRegisterBean()方法:
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {/*** 根據指定的bean創建一個AnnotatedGenericBeanDefinition* 這個AnnotatedGenericBeanDefinition可以理解為一個數據結構* AnnotatedGenericBeanDefinition包含了類的其他信息,比如一些元信息* scope,lazy等等*/AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);/*** 判斷這個類是否需要跳過解析* 通過代碼可以知道spring判斷是否跳過解析,主要判斷類有沒有加注解*/if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}//不知道abd.setInstanceSupplier(instanceSupplier);/*** 得到類的作用域*/ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);/*** 把類的作用域添加到數據結構結構中*/abd.setScope(scopeMetadata.getScopeName());/*** 生成類的名字通過beanNameGenerator*/String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));/*** 處理類當中的通用注解* 分析源碼可以知道他主要處理* Lazy DependsOn Primary Role等等注解* 處理完成之后processCommonDefinitionAnnotations中依然是把他添加到數據結構當中**/AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);//這里qualifiers傳過來是null/*** 如果在向容器注冊注解Bean定義時,使用了額外的限定符注解則解析* 關于Qualifier和Primary前面的課當中講過,主要涉及到spring的自動裝配* 這里需要注意的* byName和qualifiers這個變量是Annotation類型的數組,里面存不僅僅是Qualifier注解* 理論上里面里面存的是一切注解,所以可以看到下面的代碼spring去循環了這個數組* 然后依次判斷了注解當中是否包含了Primary,是否包含了Lazyd*/if (qualifiers != null) {for (Class<? extends Annotation> qualifier : qualifiers) {如果配置了@Primary注解,如果加了則作為首選if (Primary.class == qualifier) {abd.setPrimary(true);}//懶加載,前面加過else if (Lazy.class == qualifier) {abd.setLazyInit(true);}else {//如果使用了除@Primary和@Lazy以外的其他注解,則為該Bean添加一個根據名字自動裝配的限定符//這里難以理解,后面會詳細介紹abd.addQualifier(new AutowireCandidateQualifier(qualifier));}}}for (BeanDefinitionCustomizer customizer : definitionCustomizers) {customizer.customize(abd);}/*** 這個BeanDefinitionHolder也是一個數據結構*/BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);/*** ScopedProxyMode需要結合web去理解* */definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);/*** 把上述的這個數據結構注冊給registry* registy就是AnnotatonConfigApplicationContext* AnnotatonConfigApplicationContext在初始化的時候通過調用父類的構造方法* 實例化了一個DefaultListableBeanFactory* *registerBeanDefinition里面就是把definitionHolder這個數據結構包含的信息注冊到* DefaultListableBeanFactory這個工廠*/BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }(1)先把要注冊的bean轉為AnnotatedGenericBeanDefinition(AGBD),AnnotatedGenericBeanDefinition包括了bean的其他信息,比如一些元信息,scope,lazy等。
(2)把類的作用域的名字添加到AGBD中,并且得到注冊bean的名字。processCommonDefinitionAnnotations()方法將AGBD中的信息拿出來進行處理,主要處理一些常用的注解,處理完成放回AGBD。
(3)把AnnotatedGenericBeanDefinition裝入BeanDefinitionHolder,然后BeanDefinitionRegistry把BeanDefinitionHolder中的信息(bean)注冊進入工廠。
初始化Spring環境
5.進入refresh()方法。
(1)調用prepareRefresh()方法,這是刷新前的準備工作。獲取容器的當時時間,同時給容器設置同步標識。
(2)refresh()-->obtainFreshBeanFactory()-->refreshBeanFactory()獲取工廠
(3)調用prepareBeanFactory(beanFactory):給工廠設置ClassLoader,bean表達式解釋器,添加后置處理器beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))到工廠中的一個list中,在bean實例化的時候在拿出來插手。
(4)postProcessBeanFactory(beanFactory)
(5)invokeBeanFactoryPostProcessors(beanFactory),實例化并調用所有已注冊BeanFactoryPostProcessor的bean,
必須在單例bean實例化之前調用。
??? ----->invokeBeanFactoryPostProcessors(beanFactory)
??????????? ------->invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors()):getBeanFactoryPostProcessors()方法獲取自己定義的,沒有@Component的后置處理器。繼續進入invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors())方法:
???????????a.判斷beanFactory的類型是不是和注冊器BeanDefinitionRegistry一個類型。如果是的話,創建兩個list,一個是BeanFactoryPostProcessor類型,一個是BeanDefinitionRegistryPostProcessor類型。BeanDefinitionRegistryPostProcessor其實也是繼承自BeanFactoryPostProcessor,就是多擴展了一個方法。這兩個list都是處理我們自己定義的后置處理器。
?????????? b.建立一個BeanDefinitionRegistryPostProcessor類型的list叫做currentRegistryProcessors,這個list是處理Spring自帶的后置處理器,并不是我們定義的,和a中的要有所區分。在3.3中spring已經把自己內部的6個后置處理器放入beanFcatory中了。現在根據BeanDefinitionRegistryPostProcessor取出子類放入currentRegistryProcessors。這樣的話,就可以讓子類去完成一些事,避免了高度耦合。
?????????? c.把a和b中類型為BeanDefinitionRegistryPostProcessor的list合并,也就是把我們定義的和spring內置的后置處理器放在一塊。然后調用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)方法,進入方法調用擴展方法postProcessBeanDefinitionRegistry(registry)方法,也就是子類要實現該方法。這也是一個擴展點。目前學到的有三個擴展點:BeanPostProcessor,BeanPostFactoryProcessor,BeanDefinitionRegistryPostProcessor。BeanDefinitionRegistryPostProcessor繼承自BeanPostFactoryProcessor,但是又在BeanPostFactoryProcessor的基礎上進行了擴展。
???????????d.接著c講,BeanDefinitionRegistryPostProcessor的子類ConfigurationClassPostProcessor實現了postProcessBeanDefinitionRegistry(registry)方法,進入方法,調用了processConfigBeanDefinitions(registry)方法。在這個方法中,取出工廠中所有的BeanDefinition,包括自定義的以及spring內置的。從每一個BeanDefinition獲取到原始bean的元信息,判斷bean是不是加了@Configuration注解。如果是,加入到BeanDefinitionHolder的list中,如果不是,再繼續判斷是否加了@Component,@ComponentScan,@Import,@ImportResource這些注解,如果是,同樣加入到BeanDefinitionHolder的list中。接下來就是解析這些加了注解的類。調用parser.parse(candidates)方法進行解析。parse方法中調用了另外的parse(AnnotationMetadata,beanName)方法來進行解析。繼續調用processConfigurationClass()方法,繼續調用doProcessConfigurationClass()方法,在該方法中,處理@ComponentScan的信息。調用this.componentScanParser.parse()方法,該方法中定義了一個ClassPathBeanDefinitionScanner作為掃描器,繼續調用scanner.doScan()方法,這個方法是很重要的方法,用來掃描包。首先定義一個BeanDefinitionHolder,負責裝掃描出來的BeanDefinition。調用findCandidateComponents(basePackages)方法,掃描basePackage路徑下的java文件,符合條件的并把它轉成BeanDefinition類型。調用scanCandidateComponents(String basePackage)方法,把.class文件掃描出來。
?
總結
以上是生活随笔為你收集整理的Spring源码(1)的全部內容,希望文章能夠幫你解決所遇到的問題。