1.beanDefinition
檢視程式碼
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
//單例
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
//原型
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
/**
* Role hint indicating that a {@code BeanDefinition} is a major part
* of the application. Typically corresponds to a user-defined bean.
*/
int ROLE_APPLICATION = 0;
/**
* Role hint indicating that a {@code BeanDefinition} is a supporting
* part of some larger configuration, typically an outer
* {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
* {@code SUPPORT} beans are considered important enough to be aware
* of when looking more closely at a particular
* {@link org.springframework.beans.factory.parsing.ComponentDefinition},
* but not when looking at the overall configuration of an application.
*/
int ROLE_SUPPORT = 1;
/**
* Role hint indicating that a {@code BeanDefinition} is providing an
* entirely background role and has no relevance to the end-user. This hint is
* used when registering beans that are completely part of the internal workings
* of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
*/
int ROLE_INFRASTRUCTURE = 2;
// Modifiable attributes
//設定父的BeanDefinition名稱
void setParentName(@Nullable String parentName);
//獲取父的BeanDefinition名稱
String getParentName();
//設定beanClass名稱
void setBeanClassName(@Nullable String beanClassName);
//獲取beanClass名稱
@Nullable
String getBeanClassName();
//設定作用域
void setScope(@Nullable String scope);
//獲取作用域
@Nullable
String getScope();
//設定是否懶載入
void setLazyInit(boolean lazyInit);
//是懶載入
boolean isLazyInit();
//設定依賴,對應xmlDepend
void setDependsOn(@Nullable String... dependsOn);
/**
* Return the bean names that this bean depends on.
*/
@Nullable
String[] getDependsOn();
//設定自動裝配
void setAutowireCandidate(boolean autowireCandidate);
/**
* Return whether this bean is a candidate for getting autowired into some other bean.
*/
boolean isAutowireCandidate();
/**
* Set whether this bean is a primary autowire candidate.
* <p>If this value is {@code true} for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
* @see #setFallback
*/
void setPrimary(boolean primary);
/**
* Return whether this bean is a primary autowire candidate.
*/
boolean isPrimary();
/**
* Set whether this bean is a fallback autowire candidate.
* <p>If this value is {@code true} for all beans but one among multiple
* matching candidates, the remaining bean will be selected.
* @since 6.2
* @see #setPrimary
*/
void setFallback(boolean fallback);
/**
* Return whether this bean is a fallback autowire candidate.
* @since 6.2
*/
boolean isFallback();
/**
* Specify the factory bean to use, if any.
* This is the name of the bean to call the specified factory method on.
* <p>A factory bean name is only necessary for instance-based factory methods.
* For static factory methods, the method will be derived from the bean class.
* @see #setFactoryMethodName
* @see #setBeanClassName
*/
void setFactoryBeanName(@Nullable String factoryBeanName);
/**
* Return the factory bean name, if any.
* <p>This will be {@code null} for static factory methods which will
* be derived from the bean class instead.
* @see #getFactoryMethodName()
* @see #getBeanClassName()
*/
@Nullable
String getFactoryBeanName();
/**
* Specify a factory method, if any. This method will be invoked with
* constructor arguments, or with no arguments if none are specified.
* The method will be invoked on the specified factory bean, if any,
* or otherwise as a static method on the local bean class.
* @see #setFactoryBeanName
* @see #setBeanClassName
*/
void setFactoryMethodName(@Nullable String factoryMethodName);
/**
* Return a factory method, if any.
* @see #getFactoryBeanName()
* @see #getBeanClassName()
*/
@Nullable
String getFactoryMethodName();
/**
* Return the constructor argument values for this bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the ConstructorArgumentValues object (never {@code null})
*/
ConstructorArgumentValues getConstructorArgumentValues();
/**
* Return if there are constructor argument values defined for this bean.
* @since 5.0.2
* @see #getConstructorArgumentValues()
*/
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
/**
* Return the property values to be applied to a new instance of the bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the MutablePropertyValues object (never {@code null})
*/
MutablePropertyValues getPropertyValues();
/**
* Return if there are property values defined for this bean.
* @since 5.0.2
* @see #getPropertyValues()
*/
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
/**
* Set the name of the initializer method.
* @since 5.1
*/
void setInitMethodName(@Nullable String initMethodName);
/**
* Return the name of the initializer method.
* @since 5.1
*/
@Nullable
String getInitMethodName();
/**
* Set the name of the destroy method.
* @since 5.1
*/
void setDestroyMethodName(@Nullable String destroyMethodName);
/**
* Return the name of the destroy method.
* @since 5.1
*/
@Nullable
String getDestroyMethodName();
/**
* Set the role hint for this {@code BeanDefinition}. The role hint
* provides the frameworks as well as tools an indication of
* the role and importance of a particular {@code BeanDefinition}.
* @since 5.1
* @see #ROLE_APPLICATION
* @see #ROLE_SUPPORT
* @see #ROLE_INFRASTRUCTURE
*/
void setRole(int role);
/**
* Get the role hint for this {@code BeanDefinition}. The role hint
* provides the frameworks as well as tools an indication of
* the role and importance of a particular {@code BeanDefinition}.
* @see #ROLE_APPLICATION
* @see #ROLE_SUPPORT
* @see #ROLE_INFRASTRUCTURE
*/
int getRole();
/**
* Set a human-readable description of this bean definition.
* @since 5.1
*/
void setDescription(@Nullable String description);
/**
* Return a human-readable description of this bean definition.
*/
@Nullable
String getDescription();
// Read-only attributes
/**
* Return a resolvable type for this bean definition,
* based on the bean class or other specific metadata.
* <p>This is typically fully resolved on a runtime-merged bean definition
* but not necessarily on a configuration-time definition instance.
* @return the resolvable type (potentially {@link ResolvableType#NONE})
* @since 5.2
* @see ConfigurableBeanFactory#getMergedBeanDefinition
*/
ResolvableType getResolvableType();
/**
* Return whether this a <b>Singleton</b>, with a single, shared instance
* returned on all calls.
* @see #SCOPE_SINGLETON
*/
boolean isSingleton();
/**
* Return whether this a <b>Prototype</b>, with an independent instance
* returned for each call.
* @since 3.0
* @see #SCOPE_PROTOTYPE
*/
boolean isPrototype();
/**
* Return whether this bean is "abstract", that is, not meant to be instantiated
* itself but rather just serving as parent for concrete child bean definitions.
*/
boolean isAbstract();
/**
* Return a description of the resource that this bean definition
* came from (for the purpose of showing context in case of errors).
*/
@Nullable
String getResourceDescription();
/**
* Return the originating BeanDefinition, or {@code null} if none.
* <p>Allows for retrieving the decorated bean definition, if any.
* <p>Note that this method returns the immediate originator. Iterate through the
* originator chain to find the original BeanDefinition as defined by the user.
*/
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
2.AbstractBeanDefinition:定義了預設常量與方法,服務BeanDefinition
檢視程式碼
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
//定義預設的常量
public static final String SCOPE_DEFAULT = "";
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
/**
* Constant that indicates autowiring a constructor.
* @see #setAutowireMode
*/
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
/**
* Constant that indicates determining an appropriate autowire strategy
* through introspection of the bean class.
* @see #setAutowireMode
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
* use annotation-based autowiring for clearer demarcation of autowiring needs.
*/
@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
/**
* Constant that indicates no dependency check at all.
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_NONE = 0;
/**
* Constant that indicates dependency checking for object references.
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
/**
* Constant that indicates dependency checking for "simple" properties.
* @see #setDependencyCheck
* @see org.springframework.beans.BeanUtils#isSimpleProperty
*/
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
/**
* Constant that indicates dependency checking for all properties
* (object references as well as "simple" properties).
* @see #setDependencyCheck
*/
public static final int DEPENDENCY_CHECK_ALL = 3;
/**
* The name of an attribute that can be
* {@link org.springframework.core.AttributeAccessor#setAttribute set} on a
* {@link org.springframework.beans.factory.config.BeanDefinition} so that
* bean definitions can indicate one or more preferred constructors. This is
* analogous to {@code @Autowired} annotated constructors on the bean class.
* <p>The attribute value may be a single {@link java.lang.reflect.Constructor}
* reference or an array thereof.
* @since 6.1
* @see org.springframework.beans.factory.annotation.Autowired
* @see org.springframework.beans.factory.support.RootBeanDefinition#getPreferredConstructors()
*/
public static final String PREFERRED_CONSTRUCTORS_ATTRIBUTE = "preferredConstructors";
/**
* The name of an attribute that can be
* {@link org.springframework.core.AttributeAccessor#setAttribute set} on a
* {@link org.springframework.beans.factory.config.BeanDefinition} so that
* bean definitions can indicate the sort order for the targeted bean.
* This is analogous to the {@code @Order} annotation.
* @since 6.1.2
* @see org.springframework.core.annotation.Order
* @see org.springframework.core.Ordered
*/
public static final String ORDER_ATTRIBUTE = "order";
3.包掃描
無非是有兩種:
路徑+類,透過反射獲取到類。
位元組碼操作技術,直接在位元組碼中獲取後設資料,位元組碼包含這個類的一切資訊。
以下程式碼就是將
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// 掃描包路徑,classpath*:com/xxx/**/*.class 匹配這個包以及子包下的class檔案
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// URL [jar:file:/D:/sourceStudy/spring-framework/spring-study/build/libs/spring-study-6.2.0-SNAPSHOT.jar!/com/ydlclass/bean/Dog.class]
//Spring會將每一個定義的位元組碼檔案載入成為一個Resource資源
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
String filename = resource.getFilename();
if (filename != null && filename.contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
// Ignore CGLIB-generated classes in the classpath
continue;
}
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
}
}
}
catch (FileNotFoundException ex) {
if (traceEnabled) {
logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());
}
}
catch (ClassFormatException ex) {
if (shouldIgnoreClassFormatException) {
if (debugEnabled) {
logger.debug("Ignored incompatible class format in " + resource + ": " + ex.getMessage());
}
}
else {
throw new BeanDefinitionStoreException("Incompatible class format in " + resource +
": set system property 'spring.classformat.ignore' to 'true' " +
"if you mean to ignore such files during classpath scanning", ex);
}
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex);
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
3.ApplicationContext與BeanFactory區別
ApplicationContext:可以理解成高階容器,具備相對符合的能力。
ListableBeanFactory(具備beanFactoryg管理能力)
HierarchicalBeanFactory 具備分層能力
MessageSource 國籍化能力
ApplicationEventPublisher 事件傳送能力
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
...............
..............
4. refresh重新整理過程
public void refresh() throws BeansException, IllegalStateException {
this.startupShutdownLock.lock();
try {
// 啟動關閉執行緒,這個執行緒用來表示啟動當前容器使用的執行緒
// 該成員變數在之前的版本中並不存在,也是為了支援後續的併發例項化bean的情況
this.startupShutdownThread = Thread.currentThread();
// StartupStep是個小工具,用來記錄執行流程
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 為當前上下文進行重新整理前的準備
prepareRefresh();
// 此處是要初始化一個bean工廠,實時上beanFactory會在上下文構建的就建立了
// 核心的目的是為了提供一種可以進行重複重新整理的bean工廠的擴充套件,雖然我們不用
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 為工廠做一些準備工作,完成一些核心的基礎配置
// 這是spring-framework需要做的工作
// 註冊幾個和環境相關的bean,如:environment、systemProperties、systemEnvironment
prepareBeanFactory(beanFactory);
try {
// 空方法,留給子類去實現,GenericXmlApplicationContext沒有進行擴充套件
// GenericWebApplicationContext進行了擴充套件,註冊了新的作用域,處理了和servlet相關的一些工作
// 此處是spring提供給第三方的框架如spring-mvc等在容器啟動前做的配置性工作
postProcessBeanFactory(beanFactory);
// 記錄新的步驟,post-process
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 呼叫所有beanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的實現類,此時bean沒有進行例項化
// 我們可以在此處配置beanFactory,修改beanDefinition
// 此處會處理BeanDefinitionRegistryPostProcessor
// 執行流程會根據priorityOrdered Ordered noOrdered進行排序
// 單獨新增了一個listener的探測器,會在bean例項化後判斷是否是一個listener,如果是進行註冊
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊beanPostProcessor,同樣會根據priorityOrdered Ordered noOrdered進行排序
registerBeanPostProcessors(beanFactory);
// 結束步驟
beanPostProcess.end();
// 初始化上下文的messageSource
initMessageSource();
// 初始化上下文的多播器
initApplicationEventMulticaster();
// 留出空方法,讓子類擴充套件
// ServletWebServerApplicationContext進行了擴充套件,建立一個webServer,啟動tomcat
onRefresh();
// 註冊監聽器,此處listenerBean不會被例項化,會議beanName的方式註冊
// 還會處理一些早期事件
registerListeners();
// 核心:例項化所有的非懶載入的單例bean
finishBeanFactoryInitialization(beanFactory);
// 完成重新整理,釋出完成重新整理的事件
finishRefresh();
}
// 捕獲執行時異常和錯誤
catch (RuntimeException | Error ex ) {
// 如果日誌器支援警告級別,則記錄異常資訊
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 銷燬已建立的單例,以避免資源洩露
destroyBeans();
// 重置'active'標誌
cancelRefresh(ex);
// 將異常拋給呼叫者
throw ex;
}
// 無論是否丟擲異常,都會執行的程式碼塊,用於清理工作
finally {
contextRefresh.end(); // 結束上下文重新整理過程
}
}
// 無論是否丟擲異常,都會執行的程式碼塊,用於釋放資源
finally {
this.startupShutdownThread = null; // 重置啟動/關閉執行緒
this.startupShutdownLock.unlock(); // 解鎖啟動/關閉鎖
}
}