引言
其實很多同學都想通過閱讀框架的源碼以汲取框架設計思想以及編程營養,Spring
框架其實就是個很好的框架源碼學習對象。我們都知道Bean
是Spring
框架的最小操作單元,Spring
框架通過對於Bean的統一管理實現其IOC
以及AOP
等核心的框架功能,那麼Spring
框架是如何把Bean
加載到環境中來進行管理的呢?本文將圍繞這個話題進行詳細的闡述,並配合Spring
框架的源碼解析。
- Bean創建
- Bean加載流程
- 總結
一、Bean創建
在搞清楚Spring
框架如何加載Bean
之前,我們需要明確Spring
框架中的Bean
是如何被創建的。那我們就不得不談到BeanFactory
。本文采用的AnnotationConfigApplicationContext
來進行代碼示例說明,它的類繼承與實現結構如下所示。由圖可知,BeanFactory
是作爲頂級接口的形式存在。
示例代碼如下:
public class SpringTest {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(UserServiceImpl.class);
IUserService userService = (UserServiceImpl)ac.getBean("userService");
//3.執行bean中的方法
userService.query();
}
}
如示例代碼所示,在new AnnotationConfigApplicationContext(UserService.class)
創建context
過程中,實際調用了AnnotationConfigApplicationContext
的構造方法,其重載的構造方法如下所示:
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
...
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
...
}
該構造方法主要完成三件事情:
1、this()
:初始化bean讀取器以及掃描器,對應AnnotationConfigApplicationContext
的無參構造函數,如下代碼:
public AnnotationConfigApplicationContext() {
//在IOC容器中初始化一個 註解bean讀取器AnnotatedBeanDefinitionReader
this.reader = new AnnotatedBeanDefinitionReader(this);
//在IOC容器中初始化一個 按類路徑掃描註解bean的掃描器
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
2、register(annotatedClasses):進行Bean配置類註冊,如下代碼:
public void register(Class... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
在AnnotationConfigApplicationContext
上下文中,通過AnnotatedBeanDefinitionReader
調用register
進行註解Bean的讀取與註冊操作。
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容器中的AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//@Conditional裝配條件判斷是否需要跳過註冊
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//設置回調
abd.setInstanceSupplier(instanceSupplier);
//解析bean作用域(單例或者原型),如果有@Scope註解,則解析@Scope,沒有則默認爲singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//作用域寫回BeanDefinition數據結構, abd中缺損的情況下爲空,將默認值singleton重新賦值到abd
abd.setScope(scopeMetadata.getScopeName());
//生成bean配置類beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//通用註解解析到abd結構中,主要是處理Lazy, primary DependsOn, Role ,Description這五個註解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// @Qualifier特殊限定符處理
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
// 如果配置@Primary註解,則設置當前Bean爲自動裝配autowire時首選bean
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
//設置當前bean爲延遲加載
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);
//按照名稱將對應的bean註冊到IOC容器中(在下一篇文章中進行介紹)
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
3、refresh():作用爲刷新Spring的應用上下文;
刷新上下文的操作實際上是在AbstractApplicationContext
中完成的。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
...
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 準備上下文環境
prepareRefresh();
// 創建並初始化BeanFactory(這部分可以繼續追蹤,創建BeanFactory的過程)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 填充BeanFactory功能
prepareBeanFactory(beanFactory);
try {
// 提供子類覆蓋的額外處理,即子類處理自定義的BeanFactoryPostProcess
postProcessBeanFactory(beanFactory);
// 激活各種BeanFactory處理器
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊攔截Bean創建的Bean處理器,即註冊 BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 初始化上下文中的資源文件,如國際化文件的處理等
initMessageSource();
// 初始化上下文事件廣播器
initApplicationEventMulticaster();
// 給子類擴展初始化其他Bean
onRefresh();
// 在所有bean中查找listener bean,然後註冊到廣播器中
registerListeners();
// 初始化剩下的單例Bean(非延遲加載的)
finishBeanFactoryInitialization(beanFactory);
// 完成刷新過程,通知生命週期處理器lifecycleProcessor刷新過程,同時發出ContextRefreshEvent通知別人
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
//銷燬已經創建的Bean
destroyBeans();
//重置容器激活標籤
cancelRefresh(ex);
// 異常拋出
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
...
二、Bean加載
(圖片來自於網絡)
AnnotationConfigApplicationContext
繼承了AbstractApplicationContext
ublic abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
...
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
...
}
BeanFactory
接口主要的實現是在AbstractBeanFactory
中完成,doGetBean
接收以下四個參數:
(1)name
:準備獲取 bean 的名字
(2)requiredType
:準備獲取 bean 的類型
(3)args
:創建 bean 時傳遞的參數。這個參數僅限於創建 bean 時使用
(4)typeCheckOnly
:是否爲類型檢查
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
...
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//轉換Bean名稱
final String beanName = transformedBeanName(name);
Object bean;
// 從緩存中或者實例工廠中獲取 bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果容器中沒有找到,則從父類容器中加載
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 獲取依賴的 Bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 開始創建 Bean 實例,如果是單例的,那麼會創建一個單例的匿名工廠,如果是原型模式的,則不需要創建單例的工廠的,其他的如 request、session 作用域的,則根據自身的需要
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 類型檢查,如果不能進行類型轉換,則拋出異常
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
...
}
三、總結
Spring IOC
還有很多內容,本文只是管中窺豹,其他的部分將繼續在後續的文章中進行詳細介紹。