《Java Spring框架》Spring BeanDefinition源码分析
功能说明
BeanDefinition:是用于记录需要Spring初始化对象的信息,例如对象的路径,名称,修饰方式等待。
下面是BeanDefinition的继承关系图:
顶层接口BeanDefinition 每一个方法的中文注释说明:
/* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.beans.factory.config; import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.MutablePropertyValues; import org.springframework.core.AttributeAccessor; import org.springframework.lang.Nullable; /** * * @author hubt spring当中用来描述bean的一个接口 * A BeanDefinition describes a bean instance, which has property values, * constructor argument values, and further information supplied by * concrete implementations. * * <p>This is just a minimal interface: The main intention is to allow a * {@link BeanFactoryPostProcessor} such as {@link PropertyPlaceholderConfigurer} * to introspect and modify property values and other bean metadata. * * @author Juergen Hoeller * @author Rob Harrop * @since 19.03.2004 * @see ConfigurableListableBeanFactory#getBeanDefinition * @see org.springframework.beans.factory.support.RootBeanDefinition * @see org.springframework.beans.factory.support.ChildBeanDefinition */ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { /** * @author hubt 标准单例作用域的作用域标识符:“singleton”。 * Scope identifier for the standard singleton scope: "singleton". * <p>Note that extended bean factories might support further scopes. * @see #setScope */ String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; /** * @author hubt 原型 * Scope identifier for the standard prototype scope: "prototype". * <p>Note that extended bean factories might support further scopes. * @see #setScope */ String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * Role hint indicating that a {@code BeanDefinition} is a major part * of the application. Typically corresponds to a user-defined bean. * */ int ROLE_APPLICATION = 0; /** * Role hint indicating that a {@code BeanDefinition} is a supporting * part of some larger configuration, typically an outer * {@link org.springframework.beans.factory.parsing.ComponentDefinition}. * {@code SUPPORT} beans are considered important enough to be aware * of when looking more closely at a particular * {@link org.springframework.beans.factory.parsing.ComponentDefinition}, * but not when looking at the overall configuration of an application. * ROLE_SUPPORT =1实际上就是说,我这个Bean是用户的,是从配置文件中过来的 */ int ROLE_SUPPORT = 1; /** * Role hint indicating that a {@code BeanDefinition} is providing an * entirely background role and has no relevance to the end-user. This hint is * used when registering beans that are completely part of the internal workings * of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}. * 就是我这Bean是Spring自己的,和你用户没有一毛钱关系 */ int ROLE_INFRASTRUCTURE = 2; // Modifiable attributes /** * 设置一个BeanDefinition的子类,则该BeanDefinition就继承设置的子类的一些设置比如属性值,单例原型。该BeanDefinition可以不设置这些信息 * 保持和设置类一致。 * Set the name of the parent definition of this bean definition, if any. */ void setParentName(@Nullable String parentName); /** * Return the name of the parent definition of this bean definition, if any. */ @Nullable String getParentName(); /** * Specify the bean class name of this bean definition. * <p>The class name can be modified during bean factory post-processing, * typically replacing the original class name with a parsed variant of it. * @see #setParentName * @see #setFactoryBeanName * @see #setFactoryMethodName */ void setBeanClassName(@Nullable String beanClassName); /** * Return the current bean class name of this bean definition. * <p>Note that this does not have to be the actual class name used at runtime, in * case of a child definition overriding/inheriting the class name from its parent. * Also, this may just be the class that a factory method is called on, or it may * even be empty in case of a factory bean reference that a method is called on. * Hence, do <i>not</i> consider this to be the definitive bean type at runtime but * rather only use it for parsing purposes at the individual bean definition level. * @see #getParentName() * @see #getFactoryBeanName() * @see #getFactoryMethodName() */ @Nullable String getBeanClassName(); /** * Override the target scope of this bean, specifying a new scope name. * @see #SCOPE_SINGLETON * @see #SCOPE_PROTOTYPE */ void setScope(@Nullable String scope); /** * Return the name of the current target scope for this bean, * or {@code null} if not known yet. */ @Nullable String getScope(); /** * @author hubt 设置懒加载 * Set whether this bean should be lazily initialized. * <p>If {@code false}, the bean will get instantiated on startup by bean * factories that perform eager initialization of singletons. */ void setLazyInit(boolean lazyInit); /** * @author hubt 判断是否是懒加载 * Return whether this bean should be lazily initialized, i.e. not * eagerly instantiated on startup. Only applicable to a singleton bean. */ boolean isLazyInit(); /** * @author hubt 设置实例化bean 顺序。 * Set the names of the beans that this bean depends on being initialized. * The bean factory will guarantee that these beans get initialized first. */ void setDependsOn(@Nullable String... dependsOn); /** * @author hubt 获取设置DependsOn的数组。 * Return the bean names that this bean depends on. */ @Nullable String[] getDependsOn(); /** * @author hubt 可以通过该字段设置是否参与bean的注入。 true 参与,false 不参与, * 主要用途在class 名称或者类型一致时。 * Set whether this bean is a candidate for getting autowired into some other bean. * <p>Note that this flag is designed to only affect type-based autowiring. * It does not affect explicit references by name, which will get resolved even * if the specified bean is not marked as an autowire candidate. As a consequence, * autowiring by name will nevertheless inject a bean if the name matches. */ void setAutowireCandidate(boolean autowireCandidate); /** * @author hubt 根据setAutowireCandidate 设置结果判断该Bean 是否参与spring初始化。 * @author hubt 获取通过setAutowireCandidate方法设置的值。 * Return whether this bean is a candidate for getting autowired into some other bean. */ boolean isAutowireCandidate(); /** * @author hubt 注入Bean 的时候将一个Bean设置成主要可以被注入的Bean. * Set whether this bean is a primary autowire candidate. * <p>If this value is {@code true} for exactly one bean among multiple * matching candidates, it will serve as a tie-breaker. */ void setPrimary(boolean primary); /** * @author hubt 判断是否是主要bean. * Return whether this bean is a primary autowire candidate. */ boolean isPrimary(); /** * * Specify the factory bean to use, if any. * This the name of the bean to call the specified factory method on. * @see #setFactoryMethodName */ void setFactoryBeanName(@Nullable String factoryBeanName); /** * Return the factory bean name, if any. */ @Nullable String getFactoryBeanName(); /** * @author hubt 设置一个方法,该方法返回的bean 替换原来的Bean。 * Specify a factory method, if any. This method will be invoked with * constructor arguments, or with no arguments if none are specified. * The method will be invoked on the specified factory bean, if any, * or otherwise as a static method on the local bean class. * @see #setFactoryBeanName * @see #setBeanClassName */ void setFactoryMethodName(@Nullable String factoryMethodName); /** * Return a factory method, if any. */ @Nullable String getFactoryMethodName(); /** * @author hubt 存放构造函数入参的值 * Return the constructor argument values for this bean. * <p>The returned instance can be modified during bean factory post-processing. * @return the ConstructorArgumentValues object (never {@code null}) */ ConstructorArgumentValues getConstructorArgumentValues(); /** * @author hubt 判断构造方法是否传值。 * Return if there are constructor argument values defined for this bean. * @since 5.0.2 */ default boolean hasConstructorArgumentValues() { return !getConstructorArgumentValues().isEmpty(); } /** * @author hubt 获取Beanz中设置的属性值; setPropertyValues方法在其子类AbstractBeanDefinition中。 * Return the property values to be applied to a new instance of the bean. * <p>The returned instance can be modified during bean factory post-processing. * @return the MutablePropertyValues object (never {@code null}) */ MutablePropertyValues getPropertyValues(); /** * @author hubt 判断是否存在设置的属性值。 * Return if there are property values values defined for this bean. * @since 5.0.2 */ default boolean hasPropertyValues() { return !getPropertyValues().isEmpty(); } // Read-only attributes /** * @author hubt 判断是否单例 * Return whether this a <b>Singleton</b>, with a single, shared instance * returned on all calls. * @see #SCOPE_SINGLETON */ boolean isSingleton(); /** * @author hubt 判断是否原型 * Return whether this a <b>Prototype</b>, with an independent instance * returned for each call. * @since 3.0 * @see #SCOPE_PROTOTYPE */ boolean isPrototype(); /** * @author hubt 判断是否是抽象类,一般用于BeanDefinition实现类作为模板使用还是Class的Beandefinition。 * 为true 就表示是仅仅只是一个模板。 * Return whether this bean is "abstract", that is, not meant to be instantiated. */ boolean isAbstract(); /** * Get the role hint for this {@code BeanDefinition}. The role hint * provides the frameworks as well as tools with an indication of * the role and importance of a particular {@code BeanDefinition}. * @see #ROLE_APPLICATION * @see #ROLE_SUPPORT * @see #ROLE_INFRASTRUCTURE */ int getRole(); /** * @author hubt 获取描述(给Bean增加一些备注信息,无实际用途),setDescription在其子类AbstractBeanDefinition中。 * Return a human-readable description of this bean definition. */ @Nullable String getDescription(); /** * @author hubt 获取描述(对原文件java文件的描述),setResourceDescription在其子类AbstractBeanDefinition中。 * Return a description of the resource that this bean definition * came from (for the purpose of showing context in case of errors). */ @Nullable String getResourceDescription(); /** * Return the originating BeanDefinition, or {@code null} if none. * Allows for retrieving the decorated bean definition, if any. * <p>Note that this method returns the immediate originator. Iterate through the * originator chain to find the original BeanDefinition as defined by the user. */ @Nullable BeanDefinition getOriginatingBeanDefinition(); }
下面是两个辅助接口的方法说明:AttributeAccessor和BeanMetadataElement 是对BeanDefinition的扩展
/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.core; import org.springframework.lang.Nullable; /** * @author hubt 为BeanDefinition 额外提供一些类的信息,比如一些注解等。 * Interface defining a generic contract for attaching and accessing metadata * to/from arbitrary objects. * * @author Rob Harrop * @since 2.0 */ public interface AttributeAccessor { /** * Set the attribute defined by {@code name} to the supplied {@code value}. * If {@code value} is {@code null}, the attribute is {@link #removeAttribute removed}. * <p>In general, users should take care to prevent overlaps with other * metadata attributes by using fully-qualified names, perhaps using * class or package names as prefix. * @param name the unique attribute key * @param value the attribute value to be attached */ void setAttribute(String name, @Nullable Object value); /** * Get the value of the attribute identified by {@code name}. * Return {@code null} if the attribute doesn't exist. * @param name the unique attribute key * @return the current value of the attribute, if any */ @Nullable Object getAttribute(String name); /** * Remove the attribute identified by {@code name} and return its value. * Return {@code null} if no attribute under {@code name} is found. * @param name the unique attribute key * @return the last value of the attribute, if any */ @Nullable Object removeAttribute(String name); /** * Return {@code true} if the attribute identified by {@code name} exists. * Otherwise return {@code false}. * @param name the unique attribute key */ boolean hasAttribute(String name); /** * Return the names of all attributes. */ String[] attributeNames(); }
/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.beans; import org.springframework.lang.Nullable; /** * @author hubt java文件的原始路径。 * Interface to be implemented by bean metadata elements * that carry a configuration source object. * * @author Juergen Hoeller * @since 2.0 */ public interface BeanMetadataElement { /** * Return the configuration source {@code Object} for this metadata element * (may be {@code null}). */ @Nullable Object getSource(); }
AbstractBeanDefinition作为抽象类扩展BeanDefinition接口。主要讲讲三个实现类:GenericBeanDefinition、ChildBeanDefinition和RootBeanDefinition
Spring之前是没有GenericBeanDefinition,只有ChildBeanDefinition和RootBeanDefinition实现类。
RootBeanDefinition 可以作为模板,保存一些信息提供给继承版本的ChildBeanDefinition类使用。
案例:
package accelerate1.bean; public class Person { protected String name; protected String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; } }
package accelerate1.bean; public class Student extends Person { private String schoolName; public String getSchoolName() { return schoolName; } public void setSchoolName(String schoolName) { this.schoolName = schoolName; } @Override public String toString() { return "Student{" + "schoolName='" + schoolName + '\'' + "name='" + name + '\'' + "age='" + age + '\'' + '}'; } }
package accelerate1.test; import accelerate1.app.AppConfig; import accelerate1.bean.Student; import org.springframework.beans.factory.support.ChildBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Demo2 { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); annotationConfigApplicationContext.register(AppConfig.class); /** * 设置模板 */ RootBeanDefinition personBeanDefinition = new RootBeanDefinition(); personBeanDefinition.setAbstract(true); //表示该BeanDefinition作为模板不需要实例化对象。 personBeanDefinition.getPropertyValues().addPropertyValue("name","李磊"); personBeanDefinition.getPropertyValues().addPropertyValue("age","18"); /** * 继承模板,就不需要设置之前的内容,现在只需要设置不同的地方即可。 */ ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("personBeanDefinition"); childBeanDefinition.setBeanClass(Student.class); childBeanDefinition.getPropertyValues().addPropertyValue("schoolName","XXX学校"); annotationConfigApplicationContext.registerBeanDefinition("personBeanDefinition",personBeanDefinition); annotationConfigApplicationContext.registerBeanDefinition("childBeanDefinition",childBeanDefinition); annotationConfigApplicationContext.refresh(); System.out.println(annotationConfigApplicationContext.getBean(Student.class)); } }
运行结果:(与理论一致)
GenericBeanDefinition出现之后就替代了ChildBeanDefinition全部功能和大部分RootBeanDefinition的功能。
/* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.core.type; import java.util.Set; /** * @author 用于处理类上面注解的接口定义 * 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. * * @author Juergen Hoeller * @author Mark Fisher * @author Phillip Webb * @author Sam Brannen * @since 2.5 * @see StandardAnnotationMetadata * @see org.springframework.core.type.classreading.MetadataReader#getAnnotationMetadata() * @see AnnotatedTypeMetadata */ public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata { /** * @author hubt 获取所有注释类型的完全限定类名 * Get the fully qualified class names of all annotation types that * are <em>present</em> on the underlying class. * @return the annotation type names */ Set<String> getAnnotationTypes(); /** * @author hubt 获取annotationName注释类型的完全限定类名 * Get the fully qualified class names of all meta-annotation types that * are <em>present</em> on the given annotation type on the underlying class. * @param annotationName the fully qualified class name of the meta-annotation * type to look for * @return the meta-annotation type names, or an empty set if none found */ Set<String> getMetaAnnotationTypes(String annotationName); /** * @author hubt 是否存在annotationName注解 * Determine whether an annotation of the given type is <em>present</em> on * the underlying class. * @param annotationName the fully qualified class name of the annotation * type to look for * @return {@code true} if a matching annotation is present */ boolean hasAnnotation(String annotationName); /** * @author hubt 是否存在annotationName元注解 * Determine whether the underlying class has an annotation that is itself * annotated with the meta-annotation of the given type. * @param metaAnnotationName the fully qualified class name of the * meta-annotation type to look for * @return {@code true} if a matching meta-annotation is present */ boolean hasMetaAnnotation(String metaAnnotationName); /** * @author hubt 确定基础类是否存在注解或者元注解 * Determine whether the underlying class has any methods that are * annotated (or meta-annotated) with the given annotation type. * @param annotationName the fully qualified class name of the annotation * type to look for */ boolean hasAnnotatedMethods(String annotationName); /** * @author hubt 返回类中所有被注解注释的方法 * Retrieve the method metadata for all methods that are annotated * (or meta-annotated) with the given annotation type. * <p>For any returned method, {@link MethodMetadata#isAnnotated} will * return {@code true} for the given annotation type. * @param annotationName the fully qualified class name of the annotation * type to look for * @return a set of {@link MethodMetadata} for methods that have a matching * annotation. The return value will be an empty set if no methods match * the annotation type. */ Set<MethodMetadata> getAnnotatedMethods(String annotationName); }
/* * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.core.type; /** * 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. * * @author Juergen Hoeller * @author Mark Pollack * @author Chris Beams * @author Phillip Webb * @since 3.0 * @see StandardMethodMetadata * @see AnnotationMetadata#getAnnotatedMethods * @see AnnotatedTypeMetadata */ public interface MethodMetadata extends AnnotatedTypeMetadata { /** * @author hubt 返回方法名字 * Return the name of the method. */ String getMethodName(); /** * @author hubt 返回该方法所属的类的全限定名(带路径例如:com/baidu/test.java) * Return the fully-qualified name of the class that declares this method. */ String getDeclaringClassName(); /** * @author hubt 返回该方法返回类型的全限定名(带路径例如:com/baidu/test.java) * Return the fully-qualified name of this method's declared return type. * @since 4.2 */ String getReturnTypeName(); /** * @author hubt 判断是否抽象类 * Return whether the underlying method is effectively abstract: * i.e. marked as abstract on a class or declared as a regular, * non-default method in an interface. * @since 4.2 */ boolean isAbstract(); /** * @author hubt 判断是否静态 * Return whether the underlying method is declared as 'static'. */ boolean isStatic(); /** * @author hubt 判断是否Final * Return whether the underlying method is marked as 'final'. */ boolean isFinal(); /** * @author hubt 是否重写方法 * Return whether the underlying method is overridable, * i.e. not marked as static, final or private. */ boolean isOverridable(); }
/* * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.core.type; import java.util.Map; import org.springframework.lang.Nullable; import org.springframework.util.MultiValueMap; /** * Defines access to the annotations of a specific type ({@link AnnotationMetadata class} * or {@link MethodMetadata method}), in a form that does not necessarily require the * class-loading. * * @author Juergen Hoeller * @author Mark Fisher * @author Mark Pollack * @author Chris Beams * @author Phillip Webb * @author Sam Brannen * @since 4.0 * @see AnnotationMetadata * @see MethodMetadata */ public interface AnnotatedTypeMetadata { /** * @author hubt 是否存在 annotationName 注解 * Determine whether the underlying element has an annotation or meta-annotation * of the given type defined. * <p>If this method returns {@code true}, then * {@link #getAnnotationAttributes} will return a non-null Map. * @param annotationName the fully qualified class name of the annotation * type to look for * @return whether a matching annotation is defined */ boolean isAnnotated(String annotationName); /** * @author hubt 取得指定 annotationName 类型注解的所有的属性 - 值(k-v) * Retrieve the attributes of the annotation of the given type, if any (i.e. if * defined on the underlying element, as direct annotation or meta-annotation), * also taking attribute overrides on composed annotations into account. * @param annotationName the fully qualified class name of the annotation * type to look for * @return a Map of attributes, with the attribute name as key (e.g. "value") * and the defined attribute value as Map value. This return value will be * {@code null} if no matching annotation is defined. */ @Nullable Map<String, Object> getAnnotationAttributes(String annotationName); /** * @author hubt 取得指定 annotationName 类型注解的所有的属性 - 值(k-v) * classValuesAsString:若是true表示 Class用它的字符串的全类名来表示。这样可以避免Class被提前加载 * Retrieve the attributes of the annotation of the given type, if any (i.e. if * defined on the underlying element, as direct annotation or meta-annotation), * also taking attribute overrides on composed annotations into account. * @param annotationName the fully qualified class name of the annotation * type to look for * @param classValuesAsString whether to convert class references to String * class names for exposure as values in the returned Map, instead of Class * references which might potentially have to be loaded first * @return a Map of attributes, with the attribute name as key (e.g. "value") * and the defined attribute value as Map value. This return value will be * {@code null} if no matching annotation is defined. */ @Nullable Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString); /** * @author hubt 取得指定 annotationName 类型注解的所有的属性 - 值(k-v) 存在进MultiValueMap * Retrieve all attributes of all annotations of the given type, if any (i.e. if * defined on the underlying element, as direct annotation or meta-annotation). * Note that this variant does <i>not</i> take attribute overrides into account. * @param annotationName the fully qualified class name of the annotation * type to look for * @return a MultiMap of attributes, with the attribute name as key (e.g. "value") * and a list of the defined attribute values as Map value. This return value will * be {@code null} if no matching annotation is defined. * @see #getAllAnnotationAttributes(String, boolean) */ @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName); /** * @author hubt 取得指定 annotationName 类型注解的所有的属性 - 值(k-v) 存在进MultiValueMap * classValuesAsString:若是true表示 Class用它的字符串的全类名来表示。这样可以避免Class被提前加载 * Retrieve all attributes of all annotations of the given type, if any (i.e. if * defined on the underlying element, as direct annotation or meta-annotation). * Note that this variant does <i>not</i> take attribute overrides into account. * @param annotationName the fully qualified class name of the annotation * type to look for * @param classValuesAsString whether to convert class references to String * @return a MultiMap of attributes, with the attribute name as key (e.g. "value") * and a list of the defined attribute values as Map value. This return value will * be {@code null} if no matching annotation is defined. * @see #getAllAnnotationAttributes(String) */ @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString); }
说明:AnnotatedGenericBeanDefinition和ScannedGenericBeanDefinition。
AnnotatedGenericBeanDefinition作用是:用于的通过注解获取BeanDefinition的对象(比如@Bean)。
ScannedGenericBeanDefinition作用是:扫描文件将获取到的对象生成BeanDefinition。
This moment will nap, you will have a dream; But this moment study,you will interpret a dream.
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步