Spring?@Bean注解深入分析源碼執(zhí)行過程
本文將通過閱讀spring源碼,分析@Bean注解導入Bean的原理。
從AnnotationConfigApplicationContext對象的創(chuàng)建講起,因為在創(chuàng)建他的過程中,spring會先注入一系列的處理器,使用這些處理器解析@Configuration Class進而將@Bean標注的方法轉為BeanDefinition注入到容器。
其他的ApplicationContext實現(xiàn)在原理上也是一致的,只是入口不同而已。
AnnotationConfigApplicationContext創(chuàng)建
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
做了以下事情:
- 創(chuàng)建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
- 注冊Configuration Bean Class
- refresh()加載、刷新容器:包含著@Configuration Class解析
創(chuàng)建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
- AnnotatedBeanDefinitionReader - 用于編程注冊Bean類的方便適配器,ClassPathBeanDefinitionScanner的替代方案,支持使用注解方式顯示的注冊Bean類。有幾個重載的registerBean方法,可以將給定的Bean類注冊到spring容器,注冊的是AnnotatedGenericBeanDefinition對象,他提供了獲取Bean類meta信息的方法。
- ClassPathBeanDefinitionScanner - 從類路徑掃描組件并注冊到容器
在創(chuàng)建AnnotatedBeanDefinitionReader時,會向容器注冊幾個注解驅動處理器:
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
org.springframework.context.annotation.internalConfigurationAnnotationProcessor: ConfigurationClassPostProcessor
- BeanFactoryPostProcessor實現(xiàn),用于解析@Configuration類。
- 這個處理器是按優(yōu)先級排序的,因為在@Configuration類中聲明的任何Bean方法都必須在任何其他BeanFactoryPostProcessor執(zhí)行之前注冊其對應的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. 創(chuàng)建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);
}
創(chuàng)建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后文會有專門章節(jié)進行介紹。
至此,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應用的實現(xiàn)類重寫了這個方法,此處不展開分析
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循環(huán)
// 因為解析一遍之后,容器里面可能會有新的被注入的@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的父類,如果有,則需要繼續(xù)解析該父類
此處只截取與@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) {
// 獲取注解元數(shù)據(jù)
AnnotationMetadata original = sourceClass.getMetadata();
// 獲取被@Bean標注的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.
// 此處會將無序的beanMethods集轉為有序的beanMethods集,
// 因為StandardAnnotationMetadata使用的是反射方式獲取meta信息,
// 這個不保證順序,所以需要將其轉為SimpleAnnotationMetadata類型,
// 他內部使用ClassVisitor通過讀取字節(jié)碼文件,按順序解析獲取meta信息。
// 后續(xù)會有專門的章節(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的流程就結束了,后續(xù)的邏輯就是封裝 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注解的核心原理就分析完成了。后續(xù)將簡單介紹一下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.
用于獲取類的注解元數(shù)據(jù)。
他繼承了ClassMetadata接口,所以也可以獲取類的相關信息:比如類名、實現(xiàn)的接口、繼承的父類等信息。另外,他還支持獲取類的MethodMetadata集,即把類的所有方法解析之后封裝成MethodMetadata集。
實現(xiàn)類:
- StandardAnnotationMetadata - Uses standard reflection to introspect a given Class.
- SimpleAnnotationMetadata - ASM based.
StandardAnnotationMetadata類
這個類使用反射方式獲取類的注解元數(shù)據(jù)。
我們在上文介紹創(chuàng)建AnnotatedGenericBeanDefinition的過程中,看到過這個類對象的創(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);
}
實際上只是把類封裝到里面,實現(xiàn)方法里面使用反射獲取對應元數(shù)據(jù)。
SimpleAnnotationMetadata類
StandardAnnotationMetadata類獲取出來的元數(shù)據(jù)不保證順序,在需要順序的場景下不適用。
在Parse @Configuration class流程中有一個步驟是調用retrieveBeanMethodMetadata方法獲取所有@Bean標注的方法并封裝MethodMetadata集,其中有一步就是使用SimpleAnnotationMetadataReadingVisitor讀取字節(jié)碼文件,讀取過程中將類的元數(shù)據(jù)封裝到SimpleAnnotationMetadata對象,從而確保了順序。
代碼片段之前記錄過,此處再介紹一下:
// Retrieve the metadata for all @Bean methods
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
// 獲取注解元數(shù)據(jù)
AnnotationMetadata original = sourceClass.getMetadata();
// 獲取被@Bean標注的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.
// 此處會將無序的beanMethods集轉為有序的beanMethods集,
// 因為StandardAnnotationMetadata使用的是反射方式獲取meta信息,
// 這個不保證順序,所以需要將其轉為SimpleAnnotationMetadata類型,
// 他內部使用ClassVisitor通過讀取字節(jié)碼文件,按順序解析獲取meta信息。
// 后續(xù)會有專門的章節(jié)介紹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讀取字節(jié)碼文件,封裝元數(shù)據(jù)
getClassReader(resource).accept(visitor, PARSING_OPTIONS);
this.resource = resource;
this.annotationMetadata = visitor.getMetadata();
}
// 讀取字節(jié)碼文件完成之后,封裝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接口
封裝方法的元數(shù)據(jù)。
實現(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ù)。
到此這篇關于Spring @Bean注解深入分析源碼執(zhí)行過程的文章就介紹到這了,更多相關Spring @Bean注解內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Springboot @Configuration @bean注解作用解析
- Spring @Bean注解配置及使用方法解析
- SpringBoot配置@Configuration注解和@bean注解
- Spring注解驅動之關于@Bean注解指定初始化和銷毀的方法
- SpringBoot?@Configuration與@Bean注解使用介紹
- 關于spring的@Bean注解放入引用Bean中初始化失敗分析
- Spring @Bean注解的使用場景與案例實現(xiàn)
- spring中@Configuration和@Bean注解的用法
- 深入解析Spring中的@Bean注解
- 一文讀懂Spring中@Bean注解的核心作用
相關文章
Spring中@RestControllerAdvice注解的使用詳解
這篇文章主要介紹了Spring中@RestControllerAdvice注解的使用詳解,@RestControllerAdvice是一個組合注解,由@ControllerAdvice、@ResponseBody組成,而@ControllerAdvice繼承了@Component,需要的朋友可以參考下2024-01-01
BufferedWriter如何使用write方法實現(xiàn)換行
這篇文章主要介紹了BufferedWriter如何使用write方法實現(xiàn)換行的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
基于springboot redirect重定向路徑問題總結
這篇文章主要介紹了springboot redirect重定向路徑問題總結,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
使用springboot aop來實現(xiàn)讀寫分離和事物配置
這篇文章主要介紹了使用springboot aop來實現(xiàn)讀寫分離和事物配置,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04
Spring?AOP實現(xiàn)用戶登錄統(tǒng)一驗證功能
這篇文章主要為大家詳細介紹了Spring?AOP如何實現(xiàn)用戶登錄統(tǒng)一驗證功能,文中的示例代碼講解詳細,對我們學習具有一定的借鑒價值,需要的可以參考一下2023-01-01

