日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Spring BeanDefinition加载

發(fā)布時(shí)間:2024/4/13 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring BeanDefinition加载 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Spring容器里通過BeanDefinition對(duì)象來表示Bean,BeanDefinition描述了Bean的配置信息。而BeanDefinitionRegistry接口提供了向容器注冊(cè),刪除,獲取BeanDefinition對(duì)象的方法。

Spring IOC容器啟動(dòng)的時(shí)候,需要加載Bean定義信息BeanDefinition,用到了幾個(gè)非常關(guān)鍵的類:

  • AnnotatedBeanDefinitionReader
  • ClassPathBeanDefinitionScanner
  • XmlBeanDefinitionReader

BeanDefinition

繼承圖

BeanDefinition接口主要提供Bean的元數(shù)據(jù)描述信息,包括:類名、scope、屬性、構(gòu)造函數(shù)參數(shù)列表、依賴的bean、是否是單例類、是否是懶加載等。

public interface AttributeAccessor {void setAttribute(String name, @Nullable Object value);@NullableObject getAttribute(String name);@NullableObject removeAttribute(String name);boolean hasAttribute(String name);String[] attributeNames(); }public interface BeanMetadataElement {@Nullabledefault Object getSource() {return null;} }

BeanDefinition繼承了AttributeAccessor,說明它具有處理屬性的能力;
BeanDefinition繼承了BeanMetadataElement,說明它可以持有Bean元數(shù)據(jù)元素,作用是可以持有XML文件的一個(gè)bean標(biāo)簽對(duì)應(yīng)的Object。

AnnotatedBeanDefinition

public interface AnnotatedBeanDefinition extends BeanDefinition {AnnotationMetadata getMetadata();@NullableMethodMetadata getFactoryMethodMetadata();}

AbstractBeanDefinition

ChildBeanDefinition

public class ChildBeanDefinition extends AbstractBeanDefinition {@Nullableprivate String parentName; }

RootBeanDefinition

一個(gè)RootBeanDefinition定義表明它是一個(gè)可合并的bean definition:即在spring beanFactory運(yùn)行期間,可以返回一個(gè)特定的bean。RootBeanDefinition可以作為一個(gè)重要的通用的bean definition 視圖。

RootBeanDefinition用來在配置階段進(jìn)行注冊(cè)bean definition。然后,從spring 2.5后,編寫注冊(cè)bean definition有了更好的的方法:GenericBeanDefinition。GenericBeanDefinition支持動(dòng)態(tài)定義父類依 賴,而非硬編碼作為root bean definition。其中RootBeanDefinition是最常用的實(shí)現(xiàn)類,它對(duì)應(yīng)一般性的元素標(biāo)簽

在 配置文件中可以定義父和子,父用RootBeanDefinition表示, 而子用ChildBeanDefiniton表示,而沒有父的就使用 RootBeanDefinition表示。

?

?

輔助類

BeanNameGenerator

BeanNameGenerator是bean Name的生成器。主要有2個(gè)實(shí)現(xiàn):

  • DefaultBeanNameGenerator
  • AnnotationBeanNameGenerator
    ?

DefaultBeanNameGenerator

默認(rèn)生成器,規(guī)則為:

1、如果有類名以類名作為name。

2、沒有類名,以父name +?"$child",沒有父name,以factory name +?"$created"

3、最后,如果是內(nèi)部bean,加?"#" 加上 對(duì)象hash的十六進(jìn)制表示。如果不是,加上 ?"#"? 加上同名排序后的序號(hào)


AnnotationBeanNameGenerator

注解生成器,規(guī)則為:

1、如果注解上有name,則以此為name,

2、否則為類的短名稱的駝峰寫法。

?

AnnotatedBeanDefinitionReader

屬性

//用于BeanDefinition注冊(cè)管理private final BeanDefinitionRegistry registry;//Bean名稱生成器private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;//private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();//private ConditionEvaluator conditionEvaluator;public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");Assert.notNull(environment, "Environment must not be null");this.registry = registry; //ConditionEvaluator完成條件注解的判斷,在Spring Boot中有大量的應(yīng)用this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); //這句會(huì)把一些自動(dòng)注解處理器加入到AnnotationConfigApplicationContext下的BeanFactory的BeanDefinitions中 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}

這里將AnnotationConfigApplicationContext注冊(cè)為管理BeanDefinition的BeanDefinitionRegistry,也就是說,spring中bean的管理完全交給了AnnotationConfigApplicationContext

registerAnnotationConfigProcessors()

AnnotationConfigUtils#registerAnnotationConfigProcessors(),提供了一種極為方便注冊(cè)這些BeanPostProcessor的方式(若是xml方式,配置<context:annotation-config/>,若是全注解驅(qū)動(dòng)的ApplicationContext,就默認(rèn)會(huì)執(zhí)行)

主要功能是如果未注冊(cè)以下幾個(gè)PostProcessor,則注冊(cè)默認(rèn)類型:

  • org.springframework.context.annotation.internalConfigurationAnnotationProcessor:ConfigurationClassPostProcessor

ConfigurationClassPostProcessor是一個(gè)BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor處理器,BeanDefinitionRegistryPostProcessor的處理方法能處理@Configuration等注解。ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()方法內(nèi)部處理@Configuration@Import@ImportResource和類內(nèi)部的@Bean。

  • org.springframework.context.annotation.internalAutowiredAnnotationProcessor:AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor是用來處理@Autowired注解和@Value注解的

  • org.springframework.context.annotation.internalCommonAnnotationProcessor:CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor提供對(duì)JSR-250規(guī)范注解的支持@javax.annotation.Resource、@javax.annotation.PostConstruct和@javax.annotation.PreDestroy等的支持。

  • org.springframework.context.annotation.internalPersistenceAnnotationProcessor:internalPersistenceAnnotationProcessor

internalPersistenceAnnotationProcessor提供@PersistenceContext的支持。

  • org.springframework.context.event.internalEventListenerProcessor:EventListenerMethodProcessor

EventListenerMethodProcessor提供@ EventListener 的支持。@ EventListener實(shí)在spring4.2之后出現(xiàn)的,可以在一個(gè)Bean的方法上使用@EventListener注解來自動(dòng)注冊(cè)一個(gè)ApplicationListener。

  • org.springframework.context.event.internalEventListenerFactory:DefaultEventListenerFactory

?

?

注冊(cè)bean

public void register(Class<?>... componentClasses) {for (Class<?> componentClass : componentClasses) {registerBean(componentClass);}}public void registerBean(Class<?> beanClass) {doRegisterBean(beanClass, null, null, null, null);}public void registerBean(Class<?> beanClass, @Nullable String name) {doRegisterBean(beanClass, name, null, null, null);}@SuppressWarnings("unchecked")public void registerBean(Class<?> beanClass, Class<? extends Annotation>... qualifiers) {doRegisterBean(beanClass, null, qualifiers, null, null);}@SuppressWarnings("unchecked")public void registerBean(Class<?> beanClass, @Nullable String name,Class<? extends Annotation>... qualifiers) {doRegisterBean(beanClass, name, qualifiers, null, null);}public <T> void registerBean(Class<T> beanClass, @Nullable Supplier<T> supplier) {doRegisterBean(beanClass, null, null, supplier, null);}public <T> void registerBean(Class<T> beanClass, @Nullable String name, @Nullable Supplier<T> supplier) {doRegisterBean(beanClass, name, null, supplier, null);}public <T> void registerBean(Class<T> beanClass, @Nullable String name, @Nullable Supplier<T> supplier,BeanDefinitionCustomizer... customizers) {doRegisterBean(beanClass, name, null, supplier, customizers);}

?

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,@Nullable BeanDefinitionCustomizer[] customizers) {// 先把此實(shí)體類型轉(zhuǎn)換為一個(gè)BeanDefinitionAnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);//abd.getMetadata() 元數(shù)據(jù)包括注解信息、是否內(nèi)部類、類Class基本信息等等// 此處由conditionEvaluator#shouldSkip去過濾,此Class是否是配置類// 大體邏輯為:必須有@Configuration注解。然后解析一些Condition注解,看是否排除~if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}abd.setInstanceSupplier(supplier);// 解析ScopeScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);abd.setScope(scopeMetadata.getScopeName());// 得到Bean的名稱 一般為首字母小寫(此處為AnnotationBeanNameGenerator)String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));// 設(shè)定一些注解默認(rèn)值,如lazy、Primary等等AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);if (qualifiers != null) {// 解析qualifiers,若有此注解 則primary都成為true了for (Class<? extends Annotation> qualifier : qualifiers) {if (Primary.class == qualifier) {abd.setPrimary(true);}else if (Lazy.class == qualifier) {abd.setLazyInit(true);}else {abd.addQualifier(new AutowireCandidateQualifier(qualifier));}}}// 自定義定制信息(一般都不需要)if (customizers != null) {for (BeanDefinitionCustomizer customizer : customizers) {customizer.customize(abd);}}// 下面為解析Scope是否需要代理,最后把這個(gè)Bean注冊(cè)進(jìn)去BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);}


ClassPathBeanDefinitionScanner

屬性

private final BeanDefinitionRegistry registry;private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();@Nullableprivate String[] autowireCandidatePatterns;private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();private boolean includeAnnotationConfig = true;public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {this(registry, true);}public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {this(registry, useDefaultFilters, getOrCreateEnvironment(registry));}public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment) {this(registry, useDefaultFilters, environment,(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));}public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");this.registry = registry;if (useDefaultFilters) {registerDefaultFilters();}setEnvironment(environment);setResourceLoader(resourceLoader);}

掃描

public int scan(String... basePackages) {int beanCountAtScanStart = this.registry.getBeanDefinitionCount();doScan(basePackages);// Register annotation config processors, if necessary.if (this.includeAnnotationConfig) {AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);}

?

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");// 裝載掃描到的BeanSet<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();for (String basePackage : basePackages) {// 把掃描到的Bean就放進(jìn)來了,會(huì)把該包下面所有的Bean都掃描進(jìn)去Set<BeanDefinition> candidates = findCandidateComponents(basePackage);for (BeanDefinition candidate : candidates) {ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) {// 如果是AbstractBeanDefinition,做一些處理postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}if (candidate instanceof AnnotatedBeanDefinition) {// 如果是AnnotatedBeanDefinition,做一些處理AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}//檢查第三方 生成的bean。if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}

scanCandidateComponents()

根據(jù)basePackage掃描候選的組件

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {Set<BeanDefinition> candidates = new LinkedHashSet<>();try {// 1.根據(jù)指定包名 生成包搜索路徑//通過觀察resolveBasePackage()方法的實(shí)現(xiàn), 我們可以在設(shè)置basePackage時(shí), 使用形如${}的占位符,Spring會(huì)在這里進(jìn)行替換只要在Enviroment里面就行// 本次值為:classpath*:com/fsx/config/**/*.classString packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;//2. 資源加載器 加載搜索路徑下的 所有class 轉(zhuǎn)換為 Resource[]// 拿著上面的路徑,就可以getResources獲取出所有的.class類,這個(gè)很強(qiáng)大~~~// 真正干事的為:PathMatchingResourcePatternResolver#getResources方法// 此處能掃描到兩個(gè)類AppConfig(普通類,沒任何注解標(biāo)注)和RootConfig。所以接下里就是要解析類上的注解,以及過濾掉不是候選的類(比如AppConfig)// 注意:這里會(huì)拿到類路徑下(不包含jar包內(nèi)的)的所有的.class文件 可能有上百個(gè),然后后面再交給后面進(jìn)行篩選~~~~~~~~~~~~~~~~(這個(gè)方法,其實(shí)我們也可以使用)// 當(dāng)然和getResourcePatternResolver和這個(gè)模版有關(guān) Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);boolean traceEnabled = logger.isTraceEnabled();boolean debugEnabled = logger.isDebugEnabled();for (Resource resource : resources) {if (traceEnabled) {logger.trace("Scanning " + resource);}if (resource.isReadable()) {try {//讀取類的 注解信息 和 類信息 ,兩大信息儲(chǔ)存到 MetadataReaderMetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);// 根據(jù)TypeFilter過濾排除組件。因?yàn)锳ppConfig沒有標(biāo)準(zhǔn)@Component或者子注解,所以肯定不屬于候選組件 返回false// 注意:這里一般(默認(rèn)處理的情況下)標(biāo)注了默認(rèn)注解的才會(huì)true,什么叫默認(rèn)注解呢?就是@Component或者派生注解。還有javax....的,這里省略啦if (isCandidateComponent(metadataReader)) {//把符合條件的 類轉(zhuǎn)換成 BeanDefinitionScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);sbd.setResource(resource);sbd.setSource(resource);/ 再次判斷 如果是實(shí)體類 返回true,如果是抽象類,但是抽象方法 被 @Lookup 注解注釋返回true (注意 這個(gè)和上面那個(gè)是重載的方法) // 這和上面是個(gè)重載方法 個(gè)人覺得旨在處理循環(huán)引用以及@Lookup上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 (Throwable ex) {throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex);}}else {if (traceEnabled) {logger.trace("Ignored because not readable: " + resource);}}}}catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return candidates;}


XmlBeanDefinitionReader

?

?

總結(jié)

以上是生活随笔為你收集整理的Spring BeanDefinition加载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。