Spring?BeanDefinition收集過(guò)程示例詳解
以注解方式說(shuō)明BeanDefinition的收集過(guò)程
調(diào)試代碼
以注解方式說(shuō)明BeanDefinition的收集過(guò)程,調(diào)試代碼如下:
public class AnnotationACTest {
public static void main(String[] args) {
// new一個(gè)應(yīng)用上下文的時(shí)候,會(huì)注冊(cè)一些內(nèi)部的BeanFactoryPostProcessor的beanDefinition
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(BeanConfig.class);
ac.refresh();
}
}BeanConfig
@Configuration
@ComponentScan("com.mfy.test.bean")
@EnableAspectJAutoProxy
public class BeanConfig {
@Bean
public User getUser(){
this.getWoman();
return new User();
}
@Bean("women")
public Woman getWoman(){
System.out.println("測(cè)試@Configuration的類(lèi)方法內(nèi)部調(diào)用");
return new Woman();
}
}掃描包下的某一個(gè)Bean
@Component
public class PropertyBean {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}創(chuàng)建ApplicationContext對(duì)象
創(chuàng)建出來(lái)的AnnotationConfigApplicationContext內(nèi)部會(huì)持有DefaultListableBeanFactory(實(shí)現(xiàn)了BeanFactory接口的所有方法)
public AnnotationConfigApplicationContext() {
// 隱式的會(huì)調(diào)用父類(lèi)的構(gòu)造方法,this.beanFactory = new DefaultListableBeanFactory();
// 此處會(huì)添加內(nèi)部的一些beanDefinition,存儲(chǔ)到BeanFactory的beanDefinitionMap
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}值得注意的是,創(chuàng)建AnnotatedBeanDefinitionReader的過(guò)程,會(huì)將ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor的beanDefinition加入到spring容器中;創(chuàng)建ClassPathBeanDefinitionScanner時(shí),會(huì)將@Component注解加入到includeFilters.
注入PostProcessor的代碼:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 判斷BeanFactory中不存在此BeanDefinition,添加ConfigurationClassPostProcessor
// ConfigurationClassPostProcessor類(lèi)負(fù)責(zé)解析處理所有@Configuration類(lèi),并將BeanDefinition注冊(cè)到BeanFactory中。
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// AutowiredAnnotationBeanPostProcessor類(lèi)負(fù)責(zé)處理@Autowired
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// CommonAnnotationBeanPostProcessor類(lèi)負(fù)責(zé)處理@Resource,@PostConstruct,@PreDestroy
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 省略了部分代碼
return beanDefs;
}注入@Component注解
protected void registerDefaultFilters() {
// 此處將Component注入,用于后面的識(shí)別
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
// 省略部分代碼
}通過(guò)上面的步驟,只是完成了AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext()這一行代碼的運(yùn)行.
接下來(lái),要將配置類(lèi)BeanConfig,手動(dòng)注入到創(chuàng)建出來(lái)的AnnotationConfigApplicationContext中,實(shí)際上,是委托給了AnnotatedBeanDefinitionReader來(lái)進(jìn)行配置類(lèi)的解析工作
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
// 解析給定的class對(duì)象,并存儲(chǔ)到beanDefinitionMap
this.reader.register(componentClasses);
}this.reader.register(componentClasses)這行代碼,會(huì)一直調(diào)用到doRegisterBean(),才會(huì)開(kāi)始真正的邏輯處理,其實(shí)只做了一件事,就是生成BeanConfig的BeanDefinition,并注入到spring容器中.
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
// 設(shè)置單例還是原型
abd.setScope(scopeMetadata.getScopeName());
// 設(shè)置beanName,當(dāng)傳入的name為null,按照規(guī)則,自動(dòng)生成名稱(chēng)
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 解析部分公共的注解(@Lazy,@Primary,@DependsOn,@Role,@Description),并將解析出來(lái)的信息填充到beanDefinition中
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
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);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 將解析完成的beanDefinition放入beanFactory中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}此時(shí)代碼運(yùn)行完了ac.register(BeanConfig.class),接下來(lái)要刷新容器,即運(yùn)行ac.refresh(),這個(gè)方法是所有bean進(jìn)行實(shí)例化和初始化的核心,需要重點(diǎn)分析,核心步驟如下:
獲取beanFactory
遍歷BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類(lèi),調(diào)用postProcessBeanDefinitionRegistry()方法,將BeanConfig中@ComponentScan覆蓋的bean的beanDefinition信息注冊(cè)到spring容器中
實(shí)例化,初始化所有非懶加載的單例bean
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// 獲取BeanFactory,其實(shí)是DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 設(shè)置BeanFactory的類(lèi)加載器,添加幾個(gè)BeanPostProcessor,手動(dòng)注冊(cè)幾個(gè)特殊的bean
prepareBeanFactory(beanFactory);
try {
// 擴(kuò)展點(diǎn),可以對(duì)beanFactory做修改
postProcessBeanFactory(beanFactory);
// 實(shí)例化BeanFactoryPostProcessor(new應(yīng)用上下文的時(shí)候注冊(cè)的beanDefinition)并調(diào)用,作用是修改beanDefinition的信息
// 例如internalConfigurationAnnotationProcessor,用來(lái)解析@Configuration注解類(lèi)管轄的beanDefinition信息
invokeBeanFactoryPostProcessors(beanFactory);
// 實(shí)例化各種BeanPostProcessors,并注冊(cè)到beanFactory的beanPostProcessors屬性中
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// 初始化事件廣播器(給applicationEventMulticaster賦值)
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// 注冊(cè)監(jiān)聽(tīng)器(非@EventListener注解方式,注冊(cè)的是實(shí)現(xiàn)了ApplicationListener接口的類(lèi))
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
// 省略部分代碼
}分析步驟
- 收集實(shí)現(xiàn)了PriorityOrdered接口和BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類(lèi)并調(diào)用postProcessBeanDefinitionRegistry(),其實(shí)就是調(diào)用ConfigurationClassPostProcessor,這個(gè)類(lèi)是spring中的核心類(lèi),作用是收集@Component注解的Bean信息,解析成BeanDefinition注冊(cè)到spring容器中
- 收集實(shí)現(xiàn)了Ordered接口和BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類(lèi)并調(diào)用postProcessBeanDefinitionRegistry()
- 死循環(huán)收集BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類(lèi)(排除了前面的)并調(diào)用postProcessBeanDefinitionRegistry()
- 調(diào)用前面所有BeanDefinitionRegistryPostProcessor接口的實(shí)現(xiàn)類(lèi)的postProcessBeanFactory()方法
- 收集BeanFactoryPostProcessor接口的實(shí)現(xiàn)類(lèi),也是分成實(shí)現(xiàn)了PriorityOrdered接口,Ordered接口和其他的三種情況,然后調(diào)用postProcessBeanFactory()方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 已經(jīng)完成調(diào)用的后置處理器集合
Set<String> processedBeans = new HashSet<>();
// 省略部分代碼
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 獲取實(shí)現(xiàn)了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi),排序之后,按順序調(diào)用
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 目前是調(diào)用ConfigurationClassPostProcessor,解析“配置類(lèi)”的包含的bean信息,變成beanDefinition存入map中
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 獲取實(shí)現(xiàn)了Ordered接口的BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi),排序之后,按順序調(diào)用
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 死循環(huán)獲取其他所有的BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi),排序之后,按順序調(diào)用
// 死循環(huán)BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi)的原因是,前面的BeanDefinitionRegistryPostProcessor可能會(huì)注入新的實(shí)現(xiàn)類(lèi),
// 所以必須重新再獲取并調(diào)用一遍
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 遍歷BeanDefinitionRegistryPostProcessor的實(shí)現(xiàn)類(lèi),調(diào)用postProcessBeanDefinitionRegistry()
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// 遍歷BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi),調(diào)用postProcessBeanFactory()
// 對(duì)于ConfigurationClassPostProcessor,生成“配置”類(lèi)(@Configuration)的代理類(lèi)
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 遍歷非BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi)(自己加進(jìn)來(lái)的),調(diào)用postProcessBeanFactory(),基本不會(huì)執(zhí)行
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// 遍歷非BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類(lèi)(自己加進(jìn)來(lái)的),調(diào)用postProcessBeanFactory(),基本不會(huì)執(zhí)行
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// 跳過(guò)前面已經(jīng)處理過(guò)的BeanFactoryPostProcessor實(shí)現(xiàn)類(lèi)
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 通過(guò)beanFactory的getBean(),實(shí)例化BeanFactoryPostProcessor
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}下面重點(diǎn)分析一下ConfigurationClassPostProcessor,其實(shí)就是分析processConfigBeanDefinitions(),看看是如何將bean變成beanDefinition注冊(cè)到spring容器
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
// 解析@Component,@ComponentScan,@Import,@ImportResource注解
processConfigBeanDefinitions(registry);
}processConfigBeanDefinitions()實(shí)現(xiàn)邏輯
接下來(lái),看看processConfigBeanDefinitions()的實(shí)現(xiàn)邏輯,主要流程如下:
- 獲取容器中所有已經(jīng)注冊(cè)進(jìn)來(lái)的beanName,其實(shí)此時(shí)只有一個(gè)手動(dòng)注冊(cè)進(jìn)來(lái)的BeanConfig,其他的全部都是spring自己注冊(cè)的
- 篩選出@Configuration注解的類(lèi),其實(shí)就是BeanConfig
- 創(chuàng)建ConfigurationClassParser,是個(gè)解析器,作用是解析@ComponentScan注解
- 進(jìn)行parse(),將@ComponentScan指定的包下所有@Component注解的bean變成beanDefinitiion注冊(cè)到spring容器中,同時(shí)對(duì)每一個(gè)@Component注解的bean,包裝成ConfigurationClass(封裝了注解信息metadata,beanName,beanMethods和importedResources),注冊(cè)到ConfigurationClassParser中的configurationClasses屬性
- 遍歷configurationClasses中的ConfigurationClass,處理@Bean,@Import和@ImportResource注解,其中,@Bean和@Import會(huì)生成beanDefinition注冊(cè)到spring容器中
- 找出步驟4中注冊(cè)進(jìn)來(lái)的beanDefinition,判斷這些beanDefinition是否存在@Configuration,@ComponentScan,@Component,@ImportResource和@Import注解(至于為什么沒(méi)有在步驟3中掃描到這些beanDefinition,原因是這些bean不在@ComponentScan所指定的包下),若判斷為true,則將重復(fù)步驟3~6
經(jīng)過(guò)以上步驟之后,@ComponentScan指定包下的bean都已經(jīng)變成beanDefinition注冊(cè)到spring容器中了
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
// 篩選具有@Component,@ComponentScan,@Import,@ImportResource注解信息的BeanDefinition
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 若是無(wú)xml方式配置的,此處只會(huì)篩選出@Configuration注解的類(lèi)(即ac.register(BeanConfig.class))
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 實(shí)例化ConfigurationClassParser時(shí),會(huì)new一個(gè)ComponentScanAnnotationParser對(duì)象,
// 用來(lái)解析@ComponentScan注解對(duì)應(yīng)的bean信息
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析配置類(lèi),變成beanDefinition加入beanFactory的beanDefinitionMap中
// 最終的解析過(guò)程是委托給了一個(gè)實(shí)例化的ClassPathBeanDefinitionScanner類(lèi)
// 解析出來(lái)的配置類(lèi),存儲(chǔ)在parser的configurationClasses屬性中
parser.parse(candidates);
parser.validate();
// 得到所有配置類(lèi)的bean信息
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());
}
// 通過(guò)ConfigurationClass加載更多的BeanDefinition,通過(guò)前面parser.parse(candidates),解析了@bean注解并保存在ConfigurationClass的beanMethods
// 再通過(guò)beanMethods,生成BeanDefinition信息并注冊(cè)到beanDefinitionMap中
// 將@ImportResource注解的資源引入spring
// 將@Import注解的類(lèi),生成BeanDefinition信息并注冊(cè)到beanDefinitionMap中
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 如果進(jìn)入到下面的代碼中,則表示原工程中有@Configuration注解的配置類(lèi)
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())) {
// 類(lèi)似遞歸,若@Configuration注解的配置類(lèi)管轄了另外的@Configuration(不在oldCandidateNames集合中),再次循環(huán)
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();
}
}下面重點(diǎn)分析一下步驟4,解析@ComponentScan的過(guò)程,實(shí)際上調(diào)用的是processConfigurationClass()方法,主要是循環(huán)的調(diào)用doProcessConfigurationClass(),并且每次跳出循環(huán),都會(huì)將configClass注冊(cè)到屬性configurationClasses中
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
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 import.
// Let's remove the old one and go with the new one. this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// 遞歸的處理配置類(lèi)configClass及其所繼承的父類(lèi)
// 從當(dāng)前配置類(lèi)configClass開(kāi)始向上沿著類(lèi)繼承結(jié)構(gòu)逐層執(zhí)行doProcessConfigurationClass(),
// 直到遇到的父類(lèi)是由Java提供的類(lèi)結(jié)束循環(huán)
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
// 需要被處理的配置類(lèi)configClass已經(jīng)被分析處理,將它記錄到已處理配置類(lèi)記錄
this.configurationClasses.put(configClass, configClass);
}真正處理@ComponentScan的代碼邏輯,步驟如下:
- 收集所有被@Component注解并且在@ComponentScan指定的包下的bean,轉(zhuǎn)換成beanDefinition注冊(cè)到spring容器中
- 遍歷步驟1中的beanDefinition,找出存在@Configuration,@ComponentScan,@Component,@ImportResource和@Import注解信息的beanDefinition,調(diào)用parse()方法,實(shí)際上,再次調(diào)用主要是為了解析@Bean,@ComponentScan,@ImportResource和@Import注解,目的也是為了注冊(cè)這些注解代表的beanDefinition
- 處理@Import注解
- 處理@ImportResource注解
- 處理@Bean注解
TODO 解析的流程
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// 遞歸處理內(nèi)部類(lèi)(內(nèi)部類(lèi)也有@Component注解,需要注冊(cè)到容器中)
processMemberClasses(configClass, sourceClass, filter);
}
// 處理@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.info("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) {
// 此configClass存在@ComponentScan注解,掃描獲取basePackages的所有bean信息
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();
}
// 判斷通過(guò)@ComponentScan掃描新加入的bdCand,是否存在@Configuration,@ComponentScan,@Component,@ImportResource,@Import注解,
// 若有,則再次進(jìn)入配置類(lèi)的解析處理流程
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 處理@Import注解,給configClass加入ImportBeanDefinitionRegistrar,后續(xù)會(huì)調(diào)用
// getImports(),遍歷并遞歸獲取sourceClass的所有注解中包含@import注解的value值
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// 處理@ImportResource注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 處理@Bean注解,獲取注解的方法的相關(guān)元數(shù)據(jù),比如方法名、所在類(lèi)全名、返回類(lèi)型、是否靜態(tài)、是否不可覆蓋等等信息
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}以上就是Spring BeanDefinition收集過(guò)程示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring BeanDefinition收集過(guò)程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用FastAPI和Redis實(shí)現(xiàn)實(shí)時(shí)通知方式(SSE)
本文介紹了如何使用FastAPI和Redis實(shí)現(xiàn)Server-SentEvents(SSE)來(lái)推送實(shí)時(shí)通知,Server-SentEvents是一種單向數(shù)據(jù)流技術(shù),適用于實(shí)時(shí)數(shù)據(jù)推送場(chǎng)景,FastAPI和Redis的結(jié)合可以高效地實(shí)現(xiàn)這一功能,并通過(guò)心跳機(jī)制管理連接2026-01-01
Java Web開(kāi)發(fā)中過(guò)濾器和監(jiān)聽(tīng)器使用詳解
這篇文章主要為大家詳細(xì)介紹了Java中的過(guò)濾器Filter和監(jiān)聽(tīng)器Listener的使用以及二者的區(qū)別,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-10-10
mybatis 動(dòng)態(tài)SQL巧用突破in數(shù)量限制的方案
本文主要介紹了MyBatis動(dòng)態(tài)SQL通過(guò)分塊處理突破IN子句參數(shù)數(shù)量限制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-07-07
關(guān)于最長(zhǎng)遞增子序列問(wèn)題概述
本文詳細(xì)介紹了最長(zhǎng)遞增子序列問(wèn)題的定義及兩種優(yōu)化解法:貪心+二分查找和動(dòng)態(tài)規(guī)劃+狀態(tài)壓縮,貪心+二分查找時(shí)間復(fù)雜度為O(nlogn),通過(guò)維護(hù)一個(gè)有序的“尾巴”數(shù)組來(lái)高效地找到最長(zhǎng)遞增子序列,動(dòng)態(tài)規(guī)劃+狀態(tài)壓縮則通過(guò)狀態(tài)壓縮將空間復(fù)雜度優(yōu)化至O(n)2025-02-02
關(guān)于SpingMVC的<context:component-scan>包掃描踩坑記錄
這篇文章主要介紹了關(guān)于SpingMVC的<context:component-scan>包掃描踩坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Springboot?手動(dòng)分頁(yè)查詢分批批量插入數(shù)據(jù)的實(shí)現(xiàn)流程
這篇文章主要介紹了Springboot?手動(dòng)分頁(yè)查詢分批批量插入數(shù)據(jù)的實(shí)現(xiàn)流程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07

