Spring?@Bean注解深入分析源碼執(zhí)行過程
本文將通過閱讀spring源碼,分析@Bean注解導(dǎo)入Bean的原理。
從AnnotationConfigApplicationContext對(duì)象的創(chuàng)建講起,因?yàn)樵趧?chuàng)建他的過程中,spring會(huì)先注入一系列的處理器,使用這些處理器解析@Configuration Class進(jìn)而將@Bean標(biāo)注的方法轉(zhuǎn)為BeanDefinition注入到容器。
其他的ApplicationContext實(shí)現(xiàn)在原理上也是一致的,只是入口不同而已。
AnnotationConfigApplicationContext創(chuàng)建
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); register(componentClasses); refresh(); }
做了以下事情:
- 創(chuàng)建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
- 注冊(cè)Configuration Bean Class
- refresh()加載、刷新容器:包含著@Configuration Class解析
創(chuàng)建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
- AnnotatedBeanDefinitionReader - 用于編程注冊(cè)Bean類的方便適配器,ClassPathBeanDefinitionScanner的替代方案,支持使用注解方式顯示的注冊(cè)Bean類。有幾個(gè)重載的registerBean方法,可以將給定的Bean類注冊(cè)到spring容器,注冊(cè)的是AnnotatedGenericBeanDefinition對(duì)象,他提供了獲取Bean類meta信息的方法。
- ClassPathBeanDefinitionScanner - 從類路徑掃描組件并注冊(cè)到容器
在創(chuàng)建AnnotatedBeanDefinitionReader時(shí),會(huì)向容器注冊(cè)幾個(gè)注解驅(qū)動(dòng)處理器:
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
org.springframework.context.annotation.internalConfigurationAnnotationProcessor: ConfigurationClassPostProcessor
- BeanFactoryPostProcessor實(shí)現(xiàn),用于解析@Configuration類。
- 這個(gè)處理器是按優(yōu)先級(jí)排序的,因?yàn)樵贎Configuration類中聲明的任何Bean方法都必須在任何其他BeanFactoryPostProcessor執(zhí)行之前注冊(cè)其對(duì)應(yīng)的BeanDefinition。
org.springframework.context.annotation.internalAutowiredAnnotationProcessor: AutowiredAnnotationBeanPostProcessor
- BeanPostProcessor implementation that autowires annotated fields, setter methods, and arbitrary config methods. Such members to be injected are detected through annotations: by default, Spring’s @Autowired and @Value annotations.
- Also supports JSR-330’s @Inject annotation, if available, as a direct alternative to Spring’s own @Autowired.
- @Autowired支持處理器。
org.springframework.context.annotation.internalCommonAnnotationProcessor: CommonAnnotationBeanPostProcessor
- BeanPostProcessor implementation that supports common Java annotations out of the box.
- 支持Resource、PostConstruct、PreDestroy等注解。
org.springframework.context.event.internalEventListenerProcessor: EventListenerMethodProcessor
org.springframework.context.event.internalEventListenerFactory: DefaultEventListenerFactory
ConfigurationClassPostProcessor中有支持@Bean注解的邏輯。
注冊(cè)Configuration Bean Class
register(componentClasses);
調(diào)用到AnnotatedBeanDefinitionReader的register方法:
this.reader.register(componentClasses);
AnnotatedBeanDefinitionReader類支持使用注解方式顯示的注冊(cè)Bean類。幾個(gè)重載的registerBean方法,可以將給定的Bean類注冊(cè)到spring容器,注冊(cè)的是AnnotatedGenericBeanDefinition對(duì)象,他提供了獲取Bean類meta信息的方法:
public void registerBean(Class<?> beanClass) { doRegisterBean(beanClass, null, null, null, null); } private <T> void doRegisterBean(Class<T> beanClass, String name, Class<? extends Annotation>[] qualifiers, Supplier<T> supplier, BeanDefinitionCustomizer[] customizers) { // 1. 創(chuàng)建AnnotatedGenericBeanDefinition對(duì)象,封裝StandardAnnotationMetadata用于獲取Bean的注解元信息 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); // skip判斷,暫時(shí)不做分析 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } // 2. scope、primary、lazy判斷,獲取beanName等 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); 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)); } } } // 3. 封裝 BeanDefinitionHolder注冊(cè)到容器 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }
創(chuàng)建AnnotatedGenericBeanDefinition需要稍微注意一下:
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); // AnnotatedGenericBeanDefinition構(gòu)造方法 public AnnotatedGenericBeanDefinition(Class<?> beanClass) { setBeanClass(beanClass); this.metadata = AnnotationMetadata.introspect(beanClass); } // AnnotationMetadata.introspect方法 static AnnotationMetadata introspect(Class<?> type) { return StandardAnnotationMetadata.from(type); } // StandardAnnotationMetadata.from方法 static AnnotationMetadata from(Class<?> introspectedClass) { return new StandardAnnotationMetadata(introspectedClass, true); }
以上的代碼片段分散在不同的類里面,最終AnnotatedGenericBeanDefinition對(duì)象會(huì)保存一個(gè)StandardAnnotationMetadata對(duì)象,用于獲取BeanMeta信息。
StandardAnnotationMetadata后文會(huì)有專門章節(jié)進(jìn)行介紹。
至此,spring只是將@Configuration Class作為一個(gè)AnnotatedBeanDefinition注冊(cè)到了容器中,@Configuration Class解析工作是在refresh時(shí)做的。
@Configuration Class解析
refresh方法
這段代碼在AbstractApplicationContext類中,此處只截取了與本文相關(guān)部分:
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 只有web應(yīng)用的實(shí)現(xiàn)類重寫了這個(gè)方法,此處不展開分析 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 這里開始調(diào)用BeanFactory處理器 invokeBeanFactoryPostProcessors(beanFactory);
invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate .invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); }
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法:
- 先調(diào)用BeanDefinitionRegistryPostProcessor
- 再調(diào)用BeanFactoryPostProcessor
調(diào)用BeanFactoryPostProcessor與本文分析的內(nèi)容關(guān)系不大,暫時(shí)不展開分析,重點(diǎn)看調(diào)用BeanDefinitionRegistryPostProcessor的邏輯。
入口在這里:
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
進(jìn)入到invokeBeanDefinitionRegistryPostProcessors方法:
private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } }
此時(shí),就會(huì)調(diào)用到ConfigurationClassPostProcessor類的postProcessBeanDefinitionRegistry方法。
ConfigurationClassPostProcessor類
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { // 略 // Derive further bean definitions from the configuration classes in the registry. // 從容器中已有的的@Configuration Class定義進(jìn)一步解析BeanDefinition // 此處不只會(huì)解析@Bean注解,其他的比如@Import、@ComponentScan等注解他也會(huì)解析 processConfigBeanDefinitions(registry); }
processConfigBeanDefinitions方法代碼比較多,此處只截取相關(guān)部分:
// 1. Parse each @Configuration class 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()); // 此處是一個(gè)do while循環(huán) // 因?yàn)榻馕鲆槐橹?,容器里面可能?huì)有新的被注入的@Configuration Class定義,需要進(jìn)一步解析 // 比如@Import、@ComponentScan等注解就有可能注入新的@Configuration Class定義 do { parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // 2. Read the model and create bean definitions based on its content this.reader.loadBeanDefinitions(configClasses); // ... } while (!candidates.isEmpty()); // ...
以上代碼做了兩件事:
- Parse @Configuration class
- 解析ConfigurationClass集注冊(cè)BeanDefinition
Parse @Configuration class
這個(gè)步驟是將容器里面的@Configuration Class Bean定義解析成ConfigurationClass集,ConfigurationClass封裝著@Configuration Class的元信息,包括:
- AnnotationMetadata metadata - 注解元信息
- beanName - bean名字
- Set<BeanMethod> beanMethods - 這個(gè)就是這個(gè)配置類里面使用@Bean導(dǎo)出的Bean集合
- 以及Import相關(guān)信息
入口在這里:
parser.parse(candidates);
parse方法:
public void parse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { // 進(jìn)入這個(gè)分支 parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } } this.deferredImportSelectorHandler.process(); }
之后進(jìn)入processConfigurationClass方法:
protected void processConfigurationClass( ConfigurationClass configClass, Predicate<String> filter) throws IOException { // skip判斷 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); } } // Recursively process the configuration class and its superclass hierarchy. // 遞歸從本@Configuration Class將其父類解析ConfigurationClass SourceClass sourceClass = asSourceClass(configClass, filter); do { sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); } while (sourceClass != null); this.configurationClasses.put(configClass, configClass); }
doProcessConfigurationClass方法,該方法負(fù)責(zé)解析@Configuration Class,包括以下內(nèi)容:
- 遞歸處理內(nèi)部類
- 處理@PropertySource注解
- 處理@ComponentScan注解
- 處理@Import注解
- 處理@ImportResource注解
- 處理@Bean注解
- 最后獲取以下當(dāng)前@Configuration Class的父類,如果有,則需要繼續(xù)解析該父類
此處只截取與@Bean解析相關(guān)的代碼片段:
// Process individual @Bean methods Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { // 封裝 BeanMethod添加到ConfigurationClass configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); }
retrieveBeanMethodMetadata方法:
// Retrieve the metadata for all @Bean methods private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) { // 獲取注解元數(shù)據(jù) AnnotationMetadata original = sourceClass.getMetadata(); // 獲取被@Bean標(biāo)注的Method元數(shù)據(jù)集 Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName()); if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) { // Try reading the class file via ASM for deterministic declaration order... // Unfortunately, the JVM's standard reflection returns methods in arbitrary // order, even between different runs of the same application on the same JVM. // 此處會(huì)將無序的beanMethods集轉(zhuǎn)為有序的beanMethods集, // 因?yàn)镾tandardAnnotationMetadata使用的是反射方式獲取meta信息, // 這個(gè)不保證順序,所以需要將其轉(zhuǎn)為SimpleAnnotationMetadata類型, // 他內(nèi)部使用ClassVisitor通過讀取字節(jié)碼文件,按順序解析獲取meta信息。 // 后續(xù)會(huì)有專門的章節(jié)介紹StandardAnnotationMetadata和SimpleAnnotationMetadata類 try { AnnotationMetadata asm = this.metadataReaderFactory.getMetadataReader( original.getClassName()).getAnnotationMetadata(); Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName()); if (asmMethods.size() >= beanMethods.size()) { Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size()); for (MethodMetadata asmMethod : asmMethods) { for (MethodMetadata beanMethod : beanMethods) { if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) { selectedMethods.add(beanMethod); break; } } } if (selectedMethods.size() == beanMethods.size()) { // All reflection-detected methods found in ASM method set -> proceed beanMethods = selectedMethods; } } } catch (IOException ex) { // No worries, let's continue with the reflection metadata we started with... } } return beanMethods; }
到此,解析BeanMethod和MethodMetadata的流程就結(jié)束了,后續(xù)的邏輯就是封裝 BeanDefinition并將其注冊(cè)到容器。
解析ConfigurationClass集注冊(cè)BeanDefinition
將ConfigurationClass集進(jìn)一步解析,將導(dǎo)出、掃描出的組件封裝成BeanDefinition注冊(cè)到容器:
this.reader.loadBeanDefinitions(configClasses);
loadBeanDefinitionsForConfigurationClass方法:
// Read a particular ConfigurationClass, // registering bean definitions for the class itself and all of its Bean methods. private void loadBeanDefinitionsForConfigurationClass( ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) { // skip判斷 if (trackedConditionEvaluator.shouldSkip(configClass)) { String beanName = configClass.getBeanName(); if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) { this.registry.removeBeanDefinition(beanName); } this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName()); return; } if (configClass.isImported()) { registerBeanDefinitionForImportedConfigurationClass(configClass); } // Read the given BeanMethod, // registering bean definitions with the BeanDefinitionRegistry based on its contents. for (BeanMethod beanMethod : configClass.getBeanMethods()) { loadBeanDefinitionsForBeanMethod(beanMethod); } // Import相關(guān) loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); }
loadBeanDefinitionsForBeanMethod方法,讀取指定的BeanMethod對(duì)象,將其封裝成BeanDefinition注冊(cè)到容器:
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { ConfigurationClass configClass = beanMethod.getConfigurationClass(); MethodMetadata metadata = beanMethod.getMetadata(); String methodName = metadata.getMethodName(); // Do we need to mark the bean as skipped by its condition? if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) { configClass.skippedBeanMethods.add(methodName); return; } if (configClass.skippedBeanMethods.contains(methodName)) { return; } AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class); Assert.state(bean != null, "No @Bean annotation attributes"); // Consider name and any aliases List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name"))); String beanName = (!names.isEmpty() ? names.remove(0) : methodName); // Register aliases even when overridden for (String alias : names) { this.registry.registerAlias(beanName, alias); } // Has this effectively been overridden before (e.g. via XML)? if (isOverriddenByExistingDefinition(beanMethod, beanName)) { if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) { throw new BeanDefinitionStoreException(""); } return; } ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition( configClass, metadata, beanName); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); if (metadata.isStatic()) { // static @Bean method if (configClass.getMetadata() instanceof StandardAnnotationMetadata) { beanDef.setBeanClass( ((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass()); } else { beanDef.setBeanClassName(configClass.getMetadata().getClassName()); } beanDef.setUniqueFactoryMethodName(methodName); } else { // instance @Bean method beanDef.setFactoryBeanName(configClass.getBeanName()); beanDef.setUniqueFactoryMethodName(methodName); } if (metadata instanceof StandardMethodMetadata) { beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod()); } beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor. SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE); AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata); Autowire autowire = bean.getEnum("autowire"); if (autowire.isAutowire()) { beanDef.setAutowireMode(autowire.value()); } boolean autowireCandidate = bean.getBoolean("autowireCandidate"); if (!autowireCandidate) { beanDef.setAutowireCandidate(false); } String initMethodName = bean.getString("initMethod"); if (StringUtils.hasText(initMethodName)) { beanDef.setInitMethodName(initMethodName); } String destroyMethodName = bean.getString("destroyMethod"); beanDef.setDestroyMethodName(destroyMethodName); // Consider scoping ScopedProxyMode proxyMode = ScopedProxyMode.NO; AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class); if (attributes != null) { beanDef.setScope(attributes.getString("value")); proxyMode = attributes.getEnum("proxyMode"); if (proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = ScopedProxyMode.NO; } } // Replace the original bean definition with the target one, if necessary BeanDefinition beanDefToRegister = beanDef; if (proxyMode != ScopedProxyMode.NO) { BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy( new BeanDefinitionHolder(beanDef, beanName), this.registry, proxyMode == ScopedProxyMode.TARGET_CLASS); beanDefToRegister = new ConfigurationClassBeanDefinition( (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName); } this.registry.registerBeanDefinition(beanName, beanDefToRegister); }
至此,@Bean注解的核心原理就分析完成了。后續(xù)將簡單介紹一下AnnotationMetadata和MethodMetadata這兩個(gè)接口。
AnnotationMetadata接口
Interface that defines abstract access to the annotations of a specific class, in a form that does not require that class to be loaded yet.
用于獲取類的注解元數(shù)據(jù)。
他繼承了ClassMetadata接口,所以也可以獲取類的相關(guān)信息:比如類名、實(shí)現(xiàn)的接口、繼承的父類等信息。另外,他還支持獲取類的MethodMetadata集,即把類的所有方法解析之后封裝成MethodMetadata集。
實(shí)現(xiàn)類:
- StandardAnnotationMetadata - Uses standard reflection to introspect a given Class.
- SimpleAnnotationMetadata - ASM based.
StandardAnnotationMetadata類
這個(gè)類使用反射方式獲取類的注解元數(shù)據(jù)。
我們?cè)谏衔慕榻B創(chuàng)建AnnotatedGenericBeanDefinition的過程中,看到過這個(gè)類對(duì)象的創(chuàng)建方式:
// AnnotationMetadata.introspect方法 static AnnotationMetadata introspect(Class<?> type) { return StandardAnnotationMetadata.from(type); } // StandardAnnotationMetadata.from方法 static AnnotationMetadata from(Class<?> introspectedClass) { return new StandardAnnotationMetadata(introspectedClass, true); }
實(shí)際上只是把類封裝到里面,實(shí)現(xiàn)方法里面使用反射獲取對(duì)應(yīng)元數(shù)據(jù)。
SimpleAnnotationMetadata類
StandardAnnotationMetadata類獲取出來的元數(shù)據(jù)不保證順序,在需要順序的場景下不適用。
在Parse @Configuration class流程中有一個(gè)步驟是調(diào)用retrieveBeanMethodMetadata方法獲取所有@Bean標(biāo)注的方法并封裝MethodMetadata集,其中有一步就是使用SimpleAnnotationMetadataReadingVisitor讀取字節(jié)碼文件,讀取過程中將類的元數(shù)據(jù)封裝到SimpleAnnotationMetadata對(duì)象,從而確保了順序。
代碼片段之前記錄過,此處再介紹一下:
// Retrieve the metadata for all @Bean methods private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) { // 獲取注解元數(shù)據(jù) AnnotationMetadata original = sourceClass.getMetadata(); // 獲取被@Bean標(biāo)注的Method元數(shù)據(jù)集 Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName()); if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) { // Try reading the class file via ASM for deterministic declaration order... // Unfortunately, the JVM's standard reflection returns methods in arbitrary // order, even between different runs of the same application on the same JVM. // 此處會(huì)將無序的beanMethods集轉(zhuǎn)為有序的beanMethods集, // 因?yàn)镾tandardAnnotationMetadata使用的是反射方式獲取meta信息, // 這個(gè)不保證順序,所以需要將其轉(zhuǎn)為SimpleAnnotationMetadata類型, // 他內(nèi)部使用ClassVisitor通過讀取字節(jié)碼文件,按順序解析獲取meta信息。 // 后續(xù)會(huì)有專門的章節(jié)介紹StandardAnnotationMetadata和SimpleAnnotationMetadata類 try { // 這里getMetadataReader得到的是一個(gè)SimpleMetadataReader對(duì)象 AnnotationMetadata asm = this.metadataReaderFactory.getMetadataReader( original.getClassName()).getAnnotationMetadata(); Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName()); if (asmMethods.size() >= beanMethods.size()) { Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size()); for (MethodMetadata asmMethod : asmMethods) { for (MethodMetadata beanMethod : beanMethods) { if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) { selectedMethods.add(beanMethod); break; } } } if (selectedMethods.size() == beanMethods.size()) { // All reflection-detected methods found in ASM method set -> proceed beanMethods = selectedMethods; } } } catch (IOException ex) { // No worries, let's continue with the reflection metadata we started with... } } return beanMethods; }
SimpleMetadataReader類
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException { SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader); // 這里使用SimpleAnnotationMetadataReadingVisitor讀取字節(jié)碼文件,封裝元數(shù)據(jù) getClassReader(resource).accept(visitor, PARSING_OPTIONS); this.resource = resource; this.annotationMetadata = visitor.getMetadata(); } // 讀取字節(jié)碼文件完成之后,封裝SimpleAnnotationMetadata對(duì)象 public void visitEnd() { String[] memberClassNames = StringUtils.toStringArray(this.memberClassNames); MethodMetadata[] annotatedMethods = this.annotatedMethods.toArray(new MethodMetadata[0]); MergedAnnotations annotations = MergedAnnotations.of(this.annotations); this.metadata = new SimpleAnnotationMetadata(this.className, this.access, this.enclosingClassName, this.superClassName, this.independentInnerClass, this.interfaceNames, memberClassNames, annotatedMethods, annotations); }
MethodMetadata接口
封裝方法的元數(shù)據(jù)。
實(shí)現(xiàn)類:
- StandardMethodMetadata - MethodMetadata implementation that uses standard reflection to introspect a given Method.
- SimpleMethodMetadata - ASM based.
StandardMethodMetadata
使用反射方式獲取方法元數(shù)據(jù)。
SimpleMethodMetadata
基于SimpleAnnotationMetadataReadingVisitor讀取的字節(jié)碼數(shù)據(jù),封裝方法元數(shù)據(jù)。
到此這篇關(guān)于Spring @Bean注解深入分析源碼執(zhí)行過程的文章就介紹到這了,更多相關(guān)Spring @Bean注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Springboot @Configuration @bean注解作用解析
- Spring @Bean注解配置及使用方法解析
- SpringBoot配置@Configuration注解和@bean注解
- Spring注解驅(qū)動(dòng)之關(guān)于@Bean注解指定初始化和銷毀的方法
- SpringBoot?@Configuration與@Bean注解使用介紹
- 關(guān)于spring的@Bean注解放入引用Bean中初始化失敗分析
- Spring @Bean注解的使用場景與案例實(shí)現(xiàn)
- spring中@Configuration和@Bean注解的用法
- 深入解析Spring中的@Bean注解
- 一文讀懂Spring中@Bean注解的核心作用
相關(guān)文章
Spring中@RestControllerAdvice注解的使用詳解
這篇文章主要介紹了Spring中@RestControllerAdvice注解的使用詳解,@RestControllerAdvice是一個(gè)組合注解,由@ControllerAdvice、@ResponseBody組成,而@ControllerAdvice繼承了@Component,需要的朋友可以參考下2024-01-01BufferedWriter如何使用write方法實(shí)現(xiàn)換行
這篇文章主要介紹了BufferedWriter如何使用write方法實(shí)現(xiàn)換行的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07基于springboot redirect重定向路徑問題總結(jié)
這篇文章主要介紹了springboot redirect重定向路徑問題總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09SpringBoot使用Jwt處理跨域認(rèn)證問題的教程詳解
這篇文章主要介紹了SpringBoot使用Jwt處理跨域認(rèn)證問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Java設(shè)計(jì)模式之策略模式詳細(xì)解析
這篇文章主要介紹了Java設(shè)計(jì)模式之策略模式詳細(xì)解析,策略模式中,定義算法族,分別封裝起來,讓他們之間可以相互轉(zhuǎn)化,此模式讓算法的變化獨(dú)立于使用算法的客戶,需要的朋友可以參考下2023-11-11使用springboot aop來實(shí)現(xiàn)讀寫分離和事物配置
這篇文章主要介紹了使用springboot aop來實(shí)現(xiàn)讀寫分離和事物配置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-04-04Spring?AOP實(shí)現(xiàn)用戶登錄統(tǒng)一驗(yàn)證功能
這篇文章主要為大家詳細(xì)介紹了Spring?AOP如何實(shí)現(xiàn)用戶登錄統(tǒng)一驗(yàn)證功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)具有一定的借鑒價(jià)值,需要的可以參考一下2023-01-01