Spring @Bean注解深入分析源码执行过程
作者:xuguofeng2016
本文将通过阅读spring源码,分析@Bean注解导入Bean的原理。
从AnnotationConfigApplicationContext对象的创建讲起,因为在创建他的过程中,spring会先注入一系列的处理器,使用这些处理器解析@Configuration Class进而将@Bean标注的方法转为BeanDefinition注入到容器。
其他的ApplicationContext实现在原理上也是一致的,只是入口不同而已。
AnnotationConfigApplicationContext创建
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); register(componentClasses); refresh(); }
做了以下事情:
- 创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
- 注册Configuration Bean Class
- refresh()加载、刷新容器:包含着@Configuration Class解析
创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
- AnnotatedBeanDefinitionReader - 用于编程注册Bean类的方便适配器,ClassPathBeanDefinitionScanner的替代方案,支持使用注解方式显示的注册Bean类。有几个重载的registerBean方法,可以将给定的Bean类注册到spring容器,注册的是AnnotatedGenericBeanDefinition对象,他提供了获取Bean类meta信息的方法。
- ClassPathBeanDefinitionScanner - 从类路径扫描组件并注册到容器
在创建AnnotatedBeanDefinitionReader时,会向容器注册几个注解驱动处理器:
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
org.springframework.context.annotation.internalConfigurationAnnotationProcessor: ConfigurationClassPostProcessor
- BeanFactoryPostProcessor实现,用于解析@Configuration类。
- 这个处理器是按优先级排序的,因为在@Configuration类中声明的任何Bean方法都必须在任何其他BeanFactoryPostProcessor执行之前注册其对应的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注解的逻辑。
注册Configuration Bean Class
register(componentClasses);
调用到AnnotatedBeanDefinitionReader的register方法:
this.reader.register(componentClasses);
AnnotatedBeanDefinitionReader类支持使用注解方式显示的注册Bean类。几个重载的registerBean方法,可以将给定的Bean类注册到spring容器,注册的是AnnotatedGenericBeanDefinition对象,他提供了获取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. 创建AnnotatedGenericBeanDefinition对象,封装StandardAnnotationMetadata用于获取Bean的注解元信息 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); // skip判断,暂时不做分析 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注册到容器 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }
创建AnnotatedGenericBeanDefinition需要稍微注意一下:
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); // AnnotatedGenericBeanDefinition构造方法 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对象会保存一个StandardAnnotationMetadata对象,用于获取BeanMeta信息。
StandardAnnotationMetadata后文会有专门章节进行介绍。
至此,spring只是将@Configuration Class作为一个AnnotatedBeanDefinition注册到了容器中,@Configuration Class解析工作是在refresh时做的。
@Configuration Class解析
refresh方法
这段代码在AbstractApplicationContext类中,此处只截取了与本文相关部分:
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应用的实现类重写了这个方法,此处不展开分析 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 这里开始调用BeanFactory处理器 invokeBeanFactoryPostProcessors(beanFactory);
invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate .invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); }
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法:
- 先调用BeanDefinitionRegistryPostProcessor
- 再调用BeanFactoryPostProcessor
调用BeanFactoryPostProcessor与本文分析的内容关系不大,暂时不展开分析,重点看调用BeanDefinitionRegistryPostProcessor的逻辑。
入口在这里:
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
进入到invokeBeanDefinitionRegistryPostProcessors方法:
private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } }
此时,就会调用到ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法。
ConfigurationClassPostProcessor类
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { // 略 // Derive further bean definitions from the configuration classes in the registry. // 从容器中已有的的@Configuration Class定义进一步解析BeanDefinition // 此处不只会解析@Bean注解,其他的比如@Import、@ComponentScan等注解他也会解析 processConfigBeanDefinitions(registry); }
processConfigBeanDefinitions方法代码比较多,此处只截取相关部分:
// 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()); // 此处是一个do while循环 // 因为解析一遍之后,容器里面可能会有新的被注入的@Configuration Class定义,需要进一步解析 // 比如@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集注册BeanDefinition
Parse @Configuration class
这个步骤是将容器里面的@Configuration Class Bean定义解析成ConfigurationClass集,ConfigurationClass封装着@Configuration Class的元信息,包括:
- AnnotationMetadata metadata - 注解元信息
- beanName - bean名字
- Set<BeanMethod> beanMethods - 这个就是这个配置类里面使用@Bean导出的Bean集合
- 以及Import相关信息
入口在这里:
parser.parse(candidates);
parse方法:
public void parse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { // 进入这个分支 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(); }
之后进入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方法,该方法负责解析@Configuration Class,包括以下内容:
- 递归处理内部类
- 处理@PropertySource注解
- 处理@ComponentScan注解
- 处理@Import注解
- 处理@ImportResource注解
- 处理@Bean注解
- 最后获取以下当前@Configuration Class的父类,如果有,则需要继续解析该父类
此处只截取与@Bean解析相关的代码片段:
// 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) { // 获取注解元数据 AnnotationMetadata original = sourceClass.getMetadata(); // 获取被@Bean标注的Method元数据集 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. // 此处会将无序的beanMethods集转为有序的beanMethods集, // 因为StandardAnnotationMetadata使用的是反射方式获取meta信息, // 这个不保证顺序,所以需要将其转为SimpleAnnotationMetadata类型, // 他内部使用ClassVisitor通过读取字节码文件,按顺序解析获取meta信息。 // 后续会有专门的章节介绍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的流程就结束了,后续的逻辑就是封装 BeanDefinition并将其注册到容器。
解析ConfigurationClass集注册BeanDefinition
将ConfigurationClass集进一步解析,将导出、扫描出的组件封装成BeanDefinition注册到容器:
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相关 loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); }
loadBeanDefinitionsForBeanMethod方法,读取指定的BeanMethod对象,将其封装成BeanDefinition注册到容器:
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注解的核心原理就分析完成了。后续将简单介绍一下AnnotationMetadata和MethodMetadata这两个接口。
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.
用于获取类的注解元数据。
他继承了ClassMetadata接口,所以也可以获取类的相关信息:比如类名、实现的接口、继承的父类等信息。另外,他还支持获取类的MethodMetadata集,即把类的所有方法解析之后封装成MethodMetadata集。
实现类:
- StandardAnnotationMetadata - Uses standard reflection to introspect a given Class.
- SimpleAnnotationMetadata - ASM based.
StandardAnnotationMetadata类
这个类使用反射方式获取类的注解元数据。
我们在上文介绍创建AnnotatedGenericBeanDefinition的过程中,看到过这个类对象的创建方式:
// AnnotationMetadata.introspect方法 static AnnotationMetadata introspect(Class<?> type) { return StandardAnnotationMetadata.from(type); } // StandardAnnotationMetadata.from方法 static AnnotationMetadata from(Class<?> introspectedClass) { return new StandardAnnotationMetadata(introspectedClass, true); }
实际上只是把类封装到里面,实现方法里面使用反射获取对应元数据。
SimpleAnnotationMetadata类
StandardAnnotationMetadata类获取出来的元数据不保证顺序,在需要顺序的场景下不适用。
在Parse @Configuration class流程中有一个步骤是调用retrieveBeanMethodMetadata方法获取所有@Bean标注的方法并封装MethodMetadata集,其中有一步就是使用SimpleAnnotationMetadataReadingVisitor读取字节码文件,读取过程中将类的元数据封装到SimpleAnnotationMetadata对象,从而确保了顺序。
代码片段之前记录过,此处再介绍一下:
// Retrieve the metadata for all @Bean methods private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) { // 获取注解元数据 AnnotationMetadata original = sourceClass.getMetadata(); // 获取被@Bean标注的Method元数据集 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. // 此处会将无序的beanMethods集转为有序的beanMethods集, // 因为StandardAnnotationMetadata使用的是反射方式获取meta信息, // 这个不保证顺序,所以需要将其转为SimpleAnnotationMetadata类型, // 他内部使用ClassVisitor通过读取字节码文件,按顺序解析获取meta信息。 // 后续会有专门的章节介绍StandardAnnotationMetadata和SimpleAnnotationMetadata类 try { // 这里getMetadataReader得到的是一个SimpleMetadataReader对象 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读取字节码文件,封装元数据 getClassReader(resource).accept(visitor, PARSING_OPTIONS); this.resource = resource; this.annotationMetadata = visitor.getMetadata(); } // 读取字节码文件完成之后,封装SimpleAnnotationMetadata对象 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接口
封装方法的元数据。
实现类:
- StandardMethodMetadata - MethodMetadata implementation that uses standard reflection to introspect a given Method.
- SimpleMethodMetadata - ASM based.
StandardMethodMetadata
使用反射方式获取方法元数据。
SimpleMethodMetadata
基于SimpleAnnotationMetadataReadingVisitor读取的字节码数据,封装方法元数据。
到此这篇关于Spring @Bean注解深入分析源码执行过程的文章就介绍到这了,更多相关Spring @Bean注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!