Spring 最重要的概念是 IOC 和 AOP,在IOC中最重要的有兩處,一個是建立Bean容器, 一個是初始化Bean,本章就是基於spring5.0.x講述使用AnnotationConfigApplicationContext
來說解建立Bean容器;後面文章繼續初始化Bean講解;閱讀Spring源碼是一個枯燥的過程,願君堅持下去;文章最後福利;福不福利的其實不重要,真的但願能堅持下去;java
若是以爲觀看時候來回拉滾動條不方便請使用我的博客觀看git
前面構建了Spring的源碼,在源碼中咱們寫一個啓動Spring容器的例子程序員
IndexDaogithub
public interface IndexDao {
String testSource();
}
複製代碼
IndexDaoImplweb
@Service
public class IndexDaoImpl implements IndexDao {
public IndexDaoImpl() {
System.out.println("constructor");
}
public String testSource(){
return "test \n test2";
}
}
複製代碼
AppConfigspring
@Configuration
@ComponentScan("cn.haoxy")
public class AppConfig {
}
複製代碼
TestBeanspringboot
public class TestBean {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
IndexDao bean = applicationContext.getBean(IndexDao.class);
System.out.println(bean.testSource());
applicationContext.close();
}
}
複製代碼
在build.gradle
中引入spring-context
websocket
dependencies {
compile(project(":spring-context"))
testCompile group: 'junit', name: 'junit', version: '4.12'
}
複製代碼
相似咱們在Maven構建項目時引入的session
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>
複製代碼
在看關於spring源碼的文章時不少都是基於ApplicationContext context = new ClassPathXmlApplicationContext(...)
如今都基於springboot項目不多再使用xml的方式去配置,如今不少都是基於註解的方式;因此本文咱們使用AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
來進行講解;數據結構
固然,除了這兩個之外咱們也還有其餘構建 ApplicationContext 的方案可供選擇:
FileSystemXmlApplicationContext 的構造函數須要一個 xml 配置文件在系統中的路徑,其餘和 ClassPathXmlApplicationContext 基本上同樣。
對於上面的類咱們先混個眼熟就行;後面咱們會再說到的;
第一步: 咱們確定要從AnnotationConfigApplicationContext的構造方法開始提及;
AnnotationConfigApplicationContext
有父類,故先要執行父類的構造方法;父類的構造方法實例化一個工廠DefaultListableBeanFactory
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
複製代碼
到這裏咱們再來看一個類圖:主要是BeanFactory介紹:
ApplicationContext 繼承了 ListableBeanFactory,這個 Listable 的意思就是,經過這個接口,咱們能夠獲取多個 Bean,你們看源碼會發現,最頂層 BeanFactory 接口的方法都是獲取單個 Bean 的。
ApplicationContext 繼承了 HierarchicalBeanFactory,Hierarchical 單詞自己已經能說明問題了,也就是說咱們能夠在應用中起多個 BeanFactory,而後能夠將各個 BeanFactory 設置爲父子關係。
AutowireCapableBeanFactory 這個名字中的 Autowire 你們都很是熟悉,它就是用來自動裝配 Bean 用的,可是仔細看上圖,ApplicationContext 並無繼承它,不過不用擔憂,不使用繼承,不表明不可使用組合,若是你看到 ApplicationContext 接口定義中的最後一個方法 getAutowireCapableBeanFactory() 就知道了。
ConfigurableListableBeanFactory 也是一個特殊的接口,看圖,特殊之處在於它繼承了第二層全部的三個接口,而 ApplicationContext 沒有。這點以後會用到。
而後,請讀者打開編輯器,翻一下 BeanFactory、ListableBeanFactory、HierarchicalBeanFactory、AutowireCapableBeanFactory、ApplicationContext 這幾個接口的代碼,
下面咱們着重介紹一下DefaultListableBeanFactory,咱們能夠看到 ConfigurableListableBeanFactory 只有一個實現類 DefaultListableBeanFactory,並且實現類 DefaultListableBeanFactory 還經過實現右邊的 AbstractAutowireCapableBeanFactory 通吃了右路。因此結論就是,最底下這個傢伙 DefaultListableBeanFactory 基本上是最牛的 BeanFactory 了,這也是爲何這邊會使用這個類來實例化的緣由。上面在的構造方法中實例化了DefaultListableBeanFactory,DefaultListableBeanFactory類中定義了
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
和private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
至於這兩個東西是作什麼的,咱們須要先了解一下BeanDefinition;
咱們來看下 BeanDefinition 的接口定義:
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 咱們能夠看到,默認只提供 sington 和 prototype 兩種,
// 不少讀者可能知道還有 request, session, globalSession, application, websocket 這幾種,
// 不過,它們屬於基於 web 的擴展。
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 比較不重要,直接跳過吧
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
// 設置父 Bean,這裏涉及到 bean 繼承,不是 java 繼承。請參見附錄的詳細介紹
// 一句話就是:繼承父 Bean 的配置信息而已
void setParentName(String parentName);
// 獲取父 Bean
String getParentName();
// 設置 Bean 的類名稱,未來是要經過反射來生成實例的
void setBeanClassName(String beanClassName);
// 獲取 Bean 的類名稱
String getBeanClassName();
// 設置 bean 的 scope
void setScope(String scope);
String getScope();
// 設置是否懶加載
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
// 設置該 Bean 依賴的全部的 Bean,注意,這裏的依賴不是指屬性依賴(如 @Autowire 標記的),
// 是 depends-on="" 屬性設置的值。
void setDependsOn(String... dependsOn);
// 返回該 Bean 的全部依賴
String[] getDependsOn();
// 設置該 Bean 是否能夠注入到其餘 Bean 中,只對根據類型注入有效,
// 若是根據名稱注入,即便這邊設置了 false,也是能夠的
void setAutowireCandidate(boolean autowireCandidate);
// 該 Bean 是否能夠注入到其餘 Bean 中
boolean isAutowireCandidate();
// 主要的。同一接口的多個實現,若是不指定名字的話,Spring 會優先選擇設置 primary 爲 true 的 bean
void setPrimary(boolean primary);
// 是不是 primary 的
boolean isPrimary();
// 若是該 Bean 採用工廠方法生成,指定工廠名稱。
// 一句話就是:有些實例不是用反射生成的,而是用工廠模式生成的
void setFactoryBeanName(String factoryBeanName);
// 獲取工廠名稱
String getFactoryBeanName();
// 指定工廠類中的 工廠方法名稱
void setFactoryMethodName(String factoryMethodName);
// 獲取工廠類中的 工廠方法名稱
String getFactoryMethodName();
// 構造器參數
ConstructorArgumentValues getConstructorArgumentValues();
// Bean 中的屬性值,後面給 bean 注入屬性值的時候會說到
MutablePropertyValues getPropertyValues();
// 是否 singleton
boolean isSingleton();
// 是否 prototype
boolean isPrototype();
// 若是這個 Bean 是被設置爲 abstract,那麼不能實例化,
// 經常使用於做爲 父bean 用於繼承,其實也不多用......
boolean isAbstract();
int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
複製代碼
在Java中,一切皆對象。在JDK中使用java.lang.Class
來描述類
這個對象。
在Spring中,存在bean
這樣一個概念,那Spring又是怎麼抽象bean
這個概念,用什麼類來描述bean
這個對象呢?Spring使用BeanDefinition
來描述bean
。
BeanDefinition
有不少子類例如:
咱們繼續往下看
public AnnotationConfigApplicationContext() {
/** * 建立一個讀取註解的Bean定義讀取器 */
this.reader = new AnnotatedBeanDefinitionReader(this);
//能夠用來掃描包或者類,繼而轉換成BeanDefinition
//可是實際上咱們掃描包工做不是scanner這個對象來完成的而是
//spring本身new的一個ClassPathBeanDefinitionScanner
//這裏的scanner僅僅是爲了程序員可以在外部調用AnnotationConfigApplicationContext對象的scan方法
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
複製代碼
上面代碼首先在AnnotationConfigApplicationContext構造方法中實例化了一個讀取器和掃描器;重點看上面的註釋;
緊接着看下AnnotatedBeanDefinitionReader(this);
裏面作了什麼事情
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
//AnnotationAwareOrderComparator主要能解析@Order註解和@Priority
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
//ContextAnnotationAutowireCandidateResolver提供處理延遲加載的功能
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//BeanDefinitio的註冊,這裏很重要,須要理解註冊每一個bean的類型
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//須要注意的是ConfigurationClassPostProcessor的類型是BeanDefinitionRegistryPostProcessor
//而 BeanDefinitionRegistryPostProcessor 最終實現BeanFactoryPostProcessor這個接口
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)) {
//AutowiredAnnotationBeanPostProcessor 實現了 MergedBeanDefinitionPostProcessor
//MergedBeanDefinitionPostProcessor 最終實現了 BeanPostProcessor
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//省略
........
return beanDefs;
}
複製代碼
上面代碼主要作了如下幾件事:
拿到上面在父類構造方法中實例化的一個工廠DefaultListableBeanFactory
向DefaultListableBeanFactory
工廠中添加AnnotationAwareOrderComparator
主要解析@Order
註解和@Priority
處理優先級;
向DefaultListableBeanFactory
工廠中添加ContextAnnotationAutowireCandidateResolver
提供處理延遲加載的功能
註冊spring內部本身定義的bean;並放入到beanDefinitionMap
和beanDefinitionNames
中,這裏着重看一下
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
=ConfigurationClassPostProcessor
這裏有個印象後面會再次說到;
例如:
這個方法到這裏就結束了,這就是AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
所作的事情;
咱們接着看下面applicationContext.register(AppConfig.class);
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
public void registerBean(Class<?> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}
複製代碼
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
/** * 根據指定的bean建立一個BeanDefinition的子類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);
/** * 若是傳參中帶了這些註解類就會爲true, 不然qualifiers一直爲空 * 由於這裏傳如的是null(doRegisterBean(annotatedClass, null, null, null);) */
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));
}
}
}
//這裏也爲null
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
/** * 這個BeanDefinitionHolder也是一個數據結構 */
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
/** * ScopedProxyMode 跳過 */
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
/** * 把上述的這個數據結構註冊給registry * registry就是AnnotationConfigApplicationContext * AnnotationConfigApplicationContext在初始化的時候通過調用父類的構造方法 * 實例化了一個DefaultListableBeanFactory * registerBeanDefinition裏面就是把definitionHolder這個數據結構包含的信息註冊到 * DefaultListableBeanFactory這個工廠 */
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
複製代碼
總結一下這個方法所作的事情:
根據指定的bean建立一個BeanDefinition的子類AnnotatedGenericBeanDefinition
獲得當前類的做用域,當前傳入的是AppConfig.class(默認是singleton);把類的做用域添加到AnnotatedGenericBeanDefinition中
生成bean的名字並放入BeanDefinitionHolder中
處理當前類使用的通用註解,詳細看代碼上的註釋
實例化一個BeanDefinitionHolder,至關於一箇中間媒介;來存放BeanDefinition和beanName而後註冊給registry,這裏的registry就是AnnotationConfigApplicationContext,在AnnotationConfigApplicationContext的父類中實例化了一個DefaultListableBeanFactory;DefaultListableBeanFactory中有個Map集合private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
就是在這個方法中將AppConfig.class放入到beanDefinitionMap 中的;那如今beanDefinitionMap 的size大小就是7個;能夠debbug到BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
方法中看下;最終走了org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
方法中的
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
複製代碼
applicationContext.register(AppConfig.class);
方法到這裏也就結束了;
下面咱們進入今天的重要部分:
org.springframework.context.support.AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//準備工做包括設置啓動時間,是否激活標識位,
// 初始化屬性源(property source)配置
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//返回一個factory 爲何須要返回一個工廠
//由於要對工廠進行初始化
/** 這裏說明一下:若是你使用是的xml配置的方式就會執行 AbstractRefreshableApplicationContext的refreshBeanFactory方法去加載xml配置信息; 由於ClassPathXmlApplicationContext是它的子類;如今咱們使用的是註解配置的方式因此會執行 GenericApplicationContext的refreshBeanFactory方法,這個方法就是隻返回了一個beanFactory**/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//準備工廠
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//這個方法在當前版本的spring是沒用任何代碼的
//可能spring期待在後面的版本中去擴展吧
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//在spring的環境中去執行已經被註冊的 factory processors
//設置執行自定義的ProcessBeanFactory 和spring內部本身定義的
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//註冊beanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化當前 ApplicationContext 的 MessageSource,國際化這裏就不展開說了
initMessageSource();
// Initialize event multicaster for this context.
//初始化應用事件廣播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 從方法名就能夠知道,典型的模板方法(鉤子方法),
// 具體的子類能夠在這裏初始化一些特殊的 Bean(在初始化 singleton beans 以前)
onRefresh();
// Check for listener beans and register them.
// 註冊事件監聽器,監聽器須要實現 ApplicationListener 接口。這也不是咱們的重點,過
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 重點,重點,重點
// 初始化全部的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 最後,廣播事件,ApplicationContext 初始化完成
finishRefresh();
}
//.......
複製代碼
像prepareRefresh();
,obtainFreshBeanFactory();
都沒有什麼好說的看上面的註釋就能夠,這裏咱們簡單介紹一下prepareBeanFactory(beanFactory);
方法;
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 設置 BeanFactory 的類加載器,咱們知道 BeanFactory 須要加載類,也就須要類加載器,
// 這裏設置爲加載當前 ApplicationContext 類的類加載器
beanFactory.setBeanClassLoader(getClassLoader());
//bean表達式解釋器, 爲了可以讓咱們的beanFactory去解析bean表達式
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//對象與string類型的轉換 <property red="dao">
//想深刻了解參考 https://blog.csdn.net/pentiumchen/article/details/44026575
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//添加一個後置管理器ApplicationContextAwareProcessor
// 可以在bean中得到到各類*Aware(*Aware都有其做用)
// 這個咱們很經常使用,如咱們會爲了獲取 ApplicationContext 而 implement ApplicationContextAware
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 下面幾行的意思就是,若是某個 bean 依賴於如下幾個接口的實現類,在自動裝配的時候忽略它們,
// 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);
// 下面幾行就是爲特殊的幾個 bean 賦值,若是有 bean 依賴瞭如下幾個,會注入這邊相應的值,
//MessageSource 被註冊成爲了一個普通的 bean
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 這個 BeanPostProcessor 也很簡單,在 bean 實例化後,若是是 ApplicationListener 的子類,
// 那麼將其添加到 listener 列表中,能夠理解成:註冊 事件監聽器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 這裏涉及到特殊的 bean,名爲:loadTimeWeaver,這不是咱們的重點,忽略它
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()));
}
//意思是若是自定義的Bean中沒有名爲"systemProperties"和"systemEnvironment"的Bean,
// 則註冊兩個Bena,Key爲"systemProperties"和"systemEnvironment",Value爲Map,
// 這兩個Bean就是一些系統配置和系統環境信息
// 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());
}
}
複製代碼
上面prepareBeanFactory
方法只是給beanFactory增長一些特殊的東西例如:表達式解析器,後置處理器,忽略一些特定的類;至此beanFactory中的beanDefinitionMap 的size大小依然仍是7個;
postProcessBeanFactory(beanFactory);
是一個空方法;
下面重點介紹一下invokeBeanFactoryPostProcessors(beanFactory);
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//這裏的getBeanFactoryPostProcessors()是獲取手動給spring的BeanFactoryPostProcessors()
//何爲手動給spring --> 手動調用AnnotationConfigApplicationContext.addBeanFactoryPostProcessor();
//因此說自定義的BeanFactoryPostProcessors並不是只有implements BeanFactoryPostProcessors才叫自定義
//咱們並無手動去調用因此getBeanFactoryPostProcessors()的size = 0
//這裏問: 那若是咱們本身去implements BeanFactoryPostProcessors 那getBeanFactoryPostProcessors()的size還會不會是0?
//回答: 仍是0! 由於咱們本身implements BeanFactoryPostProcessors必需要加@Component,可是直到如今爲止spring並無開始掃描@Component
//因此仍是0
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
複製代碼
進入invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
方法
下面的信息量比較大,咱們先看一下下面代碼中須要的類圖,先熟悉一下,有助於理解;
public static void invokeBeanFactoryPostProcessors( //List<BeanFactoryPostProcessor> beanFactoryPostProcessors 這個是咱們手動傳過來的 ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
//這裏確定是會進的,當前的beanFactory 一直都是 DefaultListableBeanFactory,而DefaultListableBeanFactory是BeanDefinitionRegistry的子類
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//BeanDefinitionRegistryPostProcessor繼承了BeanFactoryPostProcessor
//BeanDefinitionRegistryPostProcessor功能比BeanFactoryPostProcessor更強大
//咱們本身要是想擴展有兩種方式;1:實現BeanFactoryPostProcessor,2,BeanDefinitionRegistryPostProcessor,因此定義了兩個來存放,
//這裏之因此實例化兩個list的目的是:進行區分,spring對這兩個有不一樣的處理方式
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
//這裏是size=0;上面的代碼註釋中解釋過
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
/**如咱們本身implements BeanDefinitionRegistryPostProcessor 而且沒有加@Component而是咱們本身手動添加的 ApplicationContext.addBeanFactoryPostProcessor(new TestBeanDefinitionRegistryPostProcessor()); 那麼在下面這句話就會執行重寫的方法;**/
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
//這裏又定義了一個,和上面的區別是,這個currentRegistryProcessors 放的是spring內部本身實現了BeanDefinitionRegistryPostProcessor接口的對象
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//BeanDefinitionRegistryPostProcessor 等於 BeanFactoryPostProcessor
//getBeanNamesForType 根據bean的類型獲取bean的名字 ConfigurationClassPostProcessor
//這裏的getBeanNamesForType代碼就不展開了大體說下 就是拿到beanDefinitionNames中的7個值去對和BeanDefinitionRegistryPostProcessor對比看是不是他的子類
//這裏7箇中只有一個ConfigurationClassPostProcessor是它的子類,因此值取到了一個ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//ConfigurationClassPostProcessor咱們在最開始介紹註冊spring內部本身定義的bean時,向beanDefinitionMap添加了6個(AppConfig.calss以外)中,其中一個就是它;
//這裏解釋一下爲何要在最開始註冊這個呢?由於spring的工廠須要去解析,掃描等等功能
//而這些功能都是須要在spring工廠初始化完成以前執行
//要麼在工廠最開始的時候、要麼在工廠初始化之中,反正不能再以後
//由於若是在以後就沒有意義,由於那個時候已經須要使用工廠了
//因此這裏Spring在一開始就註冊了一個BeanFactoryPostProcessor,用來插手SpringFactory的實例化過程
//而這個類叫作ConfigurationClassPostProcessor
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//添加到集合currentRegistryProcessors中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//添加到processedBeans的Set集合中
processedBeans.add(ppName);
}
}
//排序不重要,何況currentRegistryProcessors這裏也只有一個數據
sortPostProcessors(currentRegistryProcessors, beanFactory);
//合併list,不重要(爲何要合併,由於有咱們自定義個還有spring本身內部實現的)
registryProcessors.addAll(currentRegistryProcessors);
/** * //最重要。注意這裏是方法調用 * //調用這個方法 * //循環全部的BeanDefinitionRegistryPostProcessor * //該方法內部postProcessor.postProcessBeanDefinitionRegistry */
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//這個list只是一個臨時變量,故而要清除
currentRegistryProcessors.clear();
// 下面的代碼先不看,等invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);執行完以後咱們回頭再看....
}
複製代碼
這裏就不總結了,看上面的代碼註釋就很清楚了,下面
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
是重點,咱們進去看看作了什麼事?
private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
//只有一條數據
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
複製代碼
而後執行了org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
以後執行了org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
咱們着重看下這個方法!
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//定義一個list 存放 applicationContext 提供的bd
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//獲取容器中註冊的全部bd名字 這裏會有7個
String[] candidateNames = registry.getBeanDefinitionNames();
/** * Full : 加了Configuration註解的類會被Sping標記爲Full * Lite : 其餘註解標記爲Lite */
//遍歷beanName 拿出的全部bd(BeanDefinition),而後判斷bd時候包含了@Configuration、@Import,@Compent。。。註解
//這裏循環7,可是有個6個咱們都不須要看,咱們只看AppConfig
for (String beanName : candidateNames) {
//根據bean名稱獲得具體的BeanDefinition
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//檢查是否被處理過
//若是BeanDefinition中的configurationClass屬性爲full或者lite,則意味着已經處理過了,直接跳過
//進去下面checkConfigurationClassCandidate方法就會明白這句話的意思
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//判斷是不是Configuration類,若是加了Configuration註解下面的這幾個註解就再也不判斷了
/** * candidateIndicators.add(Component.class.getName()); * candidateIndicators.add(ComponentScan.class.getName()); * candidateIndicators.add(Import.class.getName()); * candidateIndicators.add(ImportResource.class.getName()); */
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//BeanDefinitionHolder 也能夠當作一個數據結構,將BeanDefinitionHolder添加到上面實例化的一個configCandidates集合中;
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// 排序,根據order,不重要
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
//若是BeanDefinitionRegistry是SingletonBeanRegistry子類的話,
// 因爲咱們當前傳入的是DefaultListableBeanFactory,是SingletonBeanRegistry 的子類
// 所以會將registry強轉爲SingletonBeanRegistry
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 實例化ConfigurationClassParser 爲了解析各個配置類
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//實例化2個set,candidates用於將以前加入的configCandidates進行去重
//由於可能有多個配置類重複了
//alreadyParsed用於判斷是否處理過
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
//掃描包,將去重後的candidates集合傳入;裏面只有一個appConfig
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
/** * * 這裏值得注意的是掃描出來的bean當中可能包含了特殊類 * 好比ImportBeanDefinitionRegistrar那麼也在這個方法裏面處理 * 可是並非包含在configClasses當中 * configClasses當中主要包含的是importSelector * 由於ImportBeanDefinitionRegistrar在掃描出來的時候已經被添加到一個list當中去了 * */
//bd 到 map
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
複製代碼
這個方法有點長,並且很重要,須要慢慢看;在這個方法中咱們只須要針對AppConfig這個類看就能夠了其餘6個能夠跳過;
咱們先進入一下checkConfigurationClassCandidate
方法,看看是怎麼檢查註解又怎麼標識Full和Lite的;
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
//......因爲篇幅緣由,省略一些代碼,用一句話來講明一下;這個metadata是怎麼來的
/** 1,若是BeanDefinition 是 AnnotatedBeanDefinition的實例,而且className 和 BeanDefinition中的元數據的類名相同,則直接從BeanDefinition 得到Metadata 2,若是BeanDefinition 是 AbstractBeanDefinition的實例,而且beanDef 有 beanClass 屬性存在 則實例化StandardAnnotationMetadata **/
//判斷當前這個bd中存在的類是否是加了@Configruation註解
//若是存在則spring認爲他是一個全註解的類
if (isFullConfigurationCandidate(metadata)) {
//若是存在Configuration 註解,則爲BeanDefinition 設置configurationClass屬性爲full
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
//判斷是否加了如下註解,摘錄isLiteConfigurationCandidate的源碼
// candidateIndicators.add(Component.class.getName());
// candidateIndicators.add(ComponentScan.class.getName());
// candidateIndicators.add(Import.class.getName());
// candidateIndicators.add(ImportResource.class.getName());
//若是不存在Configuration註解,spring則認爲是一個部分註解類
else if (isLiteConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
複製代碼
isFullConfigurationCandidate();
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
return metadata.isAnnotated(Configuration.class.getName());
}
複製代碼
isLiteConfigurationCandidate();
static {
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
}
複製代碼
下面咱們重點分析parse
方法
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
//根據BeanDefinition 的類型 作不一樣的處理,通常都會調用ConfigurationClassParser#parse 進行解析
//遍歷configCandidates中的BeanDefinitionHolder取出BeanDefinition
//BeanDefinition中包含了AppConfig的一些屬性信息
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
//當前bd類型就是AnnotatedBeanDefinition --> true
if (bd instanceof AnnotatedBeanDefinition) {
//解析註解對象,而且把解析出來的bd放到map,可是這裏的bd指的是普通的
//何謂不普通的呢?好比@Bean 和各類beanFactoryPostProcessor獲得的bean不在這裏put
//可是這裏解析,只是put而已
//Metadata中主要包含的是解析出來的註解,當前AppConfig 解析出來的註解是@Configuration,@ComponentScan
//註解什麼時候被解析出來的呢? 就是一開始將AppConfig 加載到BeanDefinitionMap中時;
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
//處理延遲加載的importSelect
processDeferredImportSelectors();
}
複製代碼
而後進入真正的解析方法org.springframework.context.annotation.ConfigurationClassParser#parse(AnnotationMetadata, String)
在這個方法中又調用了org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
方法;
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
// 處理Imported 的狀況
//就是當前這個註解類有沒有被別的類import
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an imports.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// 遞歸地處理配置類及其超類層次結構。
SourceClass sourceClass = asSourceClass(configClass);
do {
//解析註解並掃描
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//一個map,用來存放掃描出來的bean(注意這裏的bean不是對象,僅僅bean的信息,由於還沒到實例化這一步)
this.configurationClasses.put(configClass, configClass);
}
複製代碼
而後進入doProcessConfigurationClass()
方法,下面不重要的代碼我就不貼了;
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
//處理內部類 通常不會寫內部類
processMemberClasses(configClass, sourceClass);
// 處理@PropertySource註釋
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 處理@ComponentScan註釋
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
//解析掃描的一些基本信息,好比是否過濾,好比是否加入新的包。。。。。includeFilters,excludeFilters等等都是ComponentScan中的屬性
//掃描普通類-->componentScan ---> com.haoxy
//這裏掃描出來全部@Component
//而且把掃描的出來的普通bean放到map當中
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
//檢查掃描出來的類當中是否還有@Configuration
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
//下面是處理@Import imports 3種狀況
//ImportSelector
//普通類
//ImportBeanDefinitionRegistrar
//這裏和內部地櫃調用時候的狀況不一樣
/** * 這裏處理的import是須要判斷咱們的類當中時候有@Import註解 * 若是有這把@Import當中的值拿出來,是一個類 * 好比@Import(xxxxx.class),那麼這裏便把xxxxx傳進去進行解析 * 在解析的過程當中若是發覺是一個importSelector那麼就回調selector的方法 * 返回一個字符串(類名),經過這個字符串獲得一個類 * 繼而在遞歸調用本方法來處理這個類 * * 判斷一組類是否是imports(3種import) * *代碼就不貼了,不是我們此次研究的重點 */
processImports(configClass, sourceClass, getImports(sourceClass), true);
//..........
}
複製代碼
上面的代碼就是掃描普通類----@Component,包括@Component子類: @Repository @Controller @service;而且放到了BeanDefinitionMap當中;
進入org.springframework.context.annotation.ComponentScanAnnotationParser#parse
方法;這裏就是處理ComponentScan註解中的一些屬性;例如scopedProxy
,scopeResolver
,includeFilters
,excludeFilters
,lazyInit
,basePackages
,basePackageClasses
,等...咱們直接進入parse
方法的org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
方法;這個方法把@ComponentScan中的值傳了過去;
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//獲取到包名
for (String basePackage : basePackages) {
//掃描basePackage路徑下的java文件
//符合條件的並把它轉成BeanDefinition類型
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//解析scope屬性
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//生成bean名稱
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
//若是這個類是AbstractBeanDefinition的子類
//則爲他設置默認值,好比lazy,init destory
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
//檢查而且處理經常使用的註解
//這裏的處理主要是指把經常使用註解的值設置到AnnotatedBeanDefinition當中
//當前前提是這個類必須是AnnotatedBeanDefinition類型的,說白了就是加了註解的類
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//根據包名掃描到的類加載到beanDefinition map 中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
複製代碼
掃描候選組件的類路徑方法org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
//根據索引得到bean定義,配合spring-context-indexer使用,有興趣得本身去了解一下,這裏不作具體得解析
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
//掃描得到bean定義
return scanCandidateComponents(basePackage);
}
}
複製代碼
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
//classpath*:cn/haoxy/**/*.class ant path模式串
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//這裏resources有四個;分別是 TestBean.class,AppConfig.class,IndexDao.class,IndexDaoImpl.class
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
//遍歷resources;
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//判斷是不是咱們須要的資源
/** * 經過isCandidateComponent(MetadataReader metadataReader)來根據excludeFilters和includeFilters判斷是否能夠進行下一步的操做, * 若是這個資源被排除的filter匹配上,就返回false,表明不是咱們所須要的。 * 若是被包含的filter匹配上,而且他還要經過條件判斷isConditionMatch的話,返回true,表明是咱們須要的資源,能夠進行下一步的操做。 * 這裏咱們插一句Spring有默認的includ類型的filter實現,若是上層傳入的話,就是用上層傳入的,不然就使用默認的, * 默認的是掃描@Component註解以及他的子類@Repository @Controller @service */
//顯然這裏只會匹配一個IndexDaoImpl.class
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
//........省
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
複製代碼
這裏只會有一個IndexDaoImpl
符合咱們的要求,放到candidates集合中並返回到doScan方法中;而後解析此類的做用域scope
,生成bean名稱等,而後調用registerBeanDefinition(definitionHolder, this.registry);
方法把它加入到beanDefinition
Map集合中;
下面咱們看看registerBeanDefinition(definitionHolder, this.registry)
方法
從org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
方法轉來轉去最後轉到了org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
方法;
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanNam)....
}
}
//全部的 Bean 註冊後會放入這個 beanDefinitionMap 中
//判斷beanDefinitionMap中是否存在當前bean;之因此判斷是由於咱們能夠配置容許bean覆蓋
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
//顯然這裏是不成立的,咱們並無配置容許bean覆蓋,existingDefinition中也不會存在咱們當前bean
if (existingDefinition != null) {
//若是進到這裏說明咱們容許了bean的覆蓋
if (!isAllowBeanDefinitionOverriding()) {
// 若是不容許覆蓋的話,拋異常
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName)....
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
//這裏的代碼都是打印日誌 log....
//日誌內容: 用框架定義的 Bean 覆蓋用戶自定義的 Bean
//.....
else if (!beanDefinition.equals(existingDefinition)) {
//log....
//日誌內容: 用新的 Bean 覆蓋舊的 Bean
}
else {
//log....
//日誌內容: 用同等的 Bean 覆蓋舊的 Bean,這裏指的是 equals 方法返回 true 的 Bean
}
//覆蓋bean
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//上面的if不成立就來到了這裏;若是是普通bean(IndexDaoImpl等),這裏返回是true,
// 若是是AppConfig等特殊bean,Spring一開始就加載的會走下面的else
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
//以beanName爲key,beanDefinition爲value put 到 beanDefinitionMap中;
//注意,"註冊Bean" 這個動做結束,Bean 依然尚未初始化,咱們後面會有大篇幅說初始化過程,
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
//將beanName 添加到 beanDefinitionNames集合中
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
//特殊bean
else {
// Still in startup registration phase
//一樣是以beanName爲key,beanDefinition爲value put 到 beanDefinitionMap中;
this.beanDefinitionMap.put(beanName, beanDefinition);
//將beanName 添加到 beanDefinitionNames集合中
this.beanDefinitionNames.add(beanName);
//這LinkedHashSet存放的是:environment,systemProperties,systemEnvironment
//都是一些系統環境,系統屬性,這裏對咱們不重要
this.manualSingletonNames.remove(beanName);
}
// 這個不重要,在預初始化的時候會用到,沒必要管它。
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
複製代碼
這時候beanDefinitionMap的size大小就是8個了;而後放到beanDefinitions集合中返回;這裏只是把它加入到beanDefinitionMap集合中尚未進行初始化;上面就是@ComponentScan註解做用的掃描BeanDefination的所有過程了。這一篇文章終於結束了,好累,本身總結了一遍印象更深入一些;下一篇文章開始bean的建立過程以及初始化;
福利: