1.建一個測試model
在源碼項目裏新建一個model,源碼編譯參考上一篇
建完model後在java包下添加三個類,執行成功就可以了就可以開始進行源碼閱讀了
這裏提一下還有一個ClassPathXmlApplicationContext,這個就是通過上下文去初始化Spring環境
public class Test {
public static void main(String[] args) {
//註解去初始化Spring環境
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MyAppConfig.class);
System.out.println(applicationContext.getBean(CityService.class));
}
}
@Configuration
@ComponentScan("com.demo.spring")
public class MyAppConfig {
}
@Component
public class CityService {
}
Bean的生命週期
首先我們使用IDEA點進去看一下AnnotationConfigApplicationContext,這個就是通過註解來配置Spring的上下文環境
//載入解析註冊的過程
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//父類構造函數裏,創建了一個Bean工廠
// this.beanFactory = new DefaultListableBeanFactory()
this();
//讀取和掃描器,將BeanDefinition方到Map裏
register(annotatedClasses);
refresh();
}
1.首先是this方法,this方法幹了一個什麼事情呢?
首先這個無參構造方法裏面呢
public AnnotationConfigApplicationContext() {
//創建一個讀取Bean定義的處理器,BeanDefinition
this.reader = new AnnotatedBeanDefinitionReader(this);
//掃描類轉換成BD
//僅僅爲了程序員去使用AnnotationConfigApplicationContext
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
調用子類構造方法也會調用父類構造方法
public GenericApplicationContext() {
//實例化一個工廠
this.beanFactory = new DefaultListableBeanFactory();
}
Spring工廠:
理論:產生Bean
如果Bean實現了BeanNameAware接口,工廠調用Bean的setBeanName()方法傳遞Bean的ID。(和下面的一條均屬於檢查Aware接口)
如果Bean實現了BeanFactoryAware接口,工廠調用setBeanFactory()方法傳入工廠自身
2.之後是register(annotatedClasses);方法他做了什麼呢
將傳入的appConfig.class變成BeanDefinition
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//根據指定的Bean創建一個AnnotatedGenericBeanDefinition
//這個AnnotatedGenericBeanDefinition可以理解爲一個數據結構
//包含了類的其他信息
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//判斷這個類是否要跳過解析
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
//得到類的作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//類的作用域添加到數據結構的結構當中
abd.setScope(scopeMetadata.getScopeName());
//生產Bean的名字
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//如果想容器註冊註解定義時,使用了額外的限定符註解則解析
//qualifiers是包含了註解數組
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
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 {
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);
//就是把definitionHolder一個DefaultListableFactory,registry就是ApplicationContext
//點進代碼看到map.put
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
3.最後是refresh();這個是SpringFramework裏一個主要的代碼說是最主要也不爲過。這裏呢一共調用了12個方法
@Override
public void refresh() throws BeansException, IllegalStateException {
//同步的方法
synchronized (this.startupShutdownMonitor) {
// 1.Prepare this context for refreshing.
prepareRefresh();
// 2.Tell the subclass to refresh the internal bean factory.
// 刷新beanFactory,刪除舊的beanFactory,創建新的beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3.Prepare the bean factory for use in this context.
//準備bean工廠以供在此上下文中使用。
prepareBeanFactory(beanFactory);
try {
// 4.Allows post-processing of the bean factory in context subclasses.
//允許在上下文子類中對bean工廠進行後處理。
postProcessBeanFactory(beanFactory);
// 5.Invoke factory processors registered as beans in the context.
// 調用工廠處理器,解析類信息 生成Bean
// 執行自定義的processBean ,掃描Bean 處理了import
// 掃描->putMap(RootBeanDefinition)->(1.custom)
// 程序員可以,先處理自定義的,先處理order的
invokeBeanFactoryPostProcessors(beanFactory);
// 6Register bean processors that intercept bean creation.
//註冊BeanPostProcessor前後
registerBeanPostProcessors(beanFactory);
// 7Initialize message source for this context.
initMessageSource();
// 8Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 9Initialize other special beans in specific context subclasses.
onRefresh();
// 10Check for listener beans and register them.
registerListeners();
// 11Instantiate all remaining (non-lazy-init) singletons.
// 實例化
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
(1)prepareRefresh();
//啓動事件標識位
// 設置環境變量和容器的開關標誌
(2)ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//要對工廠進行初始化
(3)準備工廠
(4)postProcessBeanFactory(beanFactory);
//允許在上下文子類中對bean工廠進行後處理。
(5)invokeBeanFactoryPostProcessors(beanFactory);
1.掃描了符合要求的class文件,各種Import註解
2.解析成BeanDefinition
ps:之前的register也是掃描 但是放入了appConfig.class 也就是AnnotationConfigApplicationContext傳入的配置類
3.put->BeanDefinitionMap->調用自定義的BeanFactoryPostProcesser,還有內置的。
/**
* 擴展原理:
* BeanPostProcessor:bean後置處理器,bean創建對象初始化前後進行攔截工作的
*
* 1、BeanFactoryPostProcessor:beanFactory的後置處理器;
* 在BeanFactory標準初始化之後調用,來定製和修改BeanFactory的內容;
* 所有的bean定義已經保存加載到beanFactory,但是bean的實例還未創建
*
*
* BeanFactoryPostProcessor原理:
* 1)、ioc容器創建對象
* 2)、invokeBeanFactoryPostProcessors(beanFactory);
* 如何找到所有的BeanFactoryPostProcessor並執行他們的方法;
* 1)、直接在BeanFactory中找到所有類型是BeanFactoryPostProcessor的組件,並執行他們的方法
* 2)、在初始化創建其他組件前面執行
*
* 2、BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
* postProcessBeanDefinitionRegistry();
* 在所有bean定義信息將要被加載,bean實例還未創建的時候;
* 優先於BeanFactoryPostProcessor執行;
* 利用BeanDefinitionRegistryPostProcessor給容器中再額外添加一些組件;
*
* 原理:
* 1)、ioc創建對象
* 2)、refresh()-》invokeBeanFactoryPostProcessors(beanFactory);
* 3)、從容器中獲取到所有的BeanDefinitionRegistryPostProcessor組件。
* 1、依次觸發所有的postProcessBeanDefinitionRegistry()方法
* 2、再來觸發postProcessBeanFactory()方法BeanFactoryPostProcessor;
*
* 4)、再來從容器中找到BeanFactoryPostProcessor組件;然後依次觸發postProcessBeanFactory()方法
*
(11)finishBeanFactoryInitialization(beanFactory);
實例化也就是new
beanFactory.preInstantiateSingletons();
//log級別
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
//所有Bean的名字
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//觸發所有非懶加載的單例Beans
for (String beanName : beanNames) {
//bdmap.get
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
} else {
//實例Bean放到單例池裏 單例池是一個ConcuretHashMap
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}