BeanDefinition就是用于描叙Spring中的Bean
Spring中关于一个Bean的基本描叙接口 --
BeanDefinition的定义:
BeanMetadataElement接口:获取Source。
public interface BeanMetadataElement { /** * Return the configuration source {@code Object} for this metadata element * (may be {@code null}). */ @Nullable Object getSource(); }
AttributeAccessor:
public interface AttributeAccessor { void setAttribute(String name, @Nullable Object value); @Nullable Object getAttribute(String name); @Nullable Object removeAttribute(String name); boolean hasAttribute(String name); String[] attributeNames(); }
其基本实现类:BeanMetadataAttributeAccessor:
public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable { private final Map<String, Object> attributes = new LinkedHashMap<>(0); @Override public void setAttribute(String name, @Nullable Object value) { Assert.notNull(name, "Name must not be null"); if (value != null) { this.attributes.put(name, value); } else { removeAttribute(name); } } .................. }
然后是其Abstract实现:AbstractBeanDefinition
此类定义了注入Bean的几种类型:
/** * Constant that indicates no autowiring at all. * @see #setAutowireMode */ public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO; public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE; public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR; @Deprecated public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
第一个是默认的,然后最后一个AUTOWIRE_AUTODETECT 已经是过时的了@Deprecated。在使用的这几种类型看名字也知道其是什么类型的了。而过时的那种,我们找到其中的一个使用的地方是会将其转换为转换为“AUTOWIRE_BY_TYPE”、“AUTOWIRE_CONSTRUCTOR”:
public int getResolvedAutowireMode() { if (this.autowireMode == AUTOWIRE_AUTODETECT) { // Work out whether to apply setter autowiring or constructor autowiring. // If it has a no-arg constructor it's deemed to be setter autowiring, // otherwise we'll try constructor autowiring. Constructor<?>[] constructors = getBeanClass().getConstructors(); for (Constructor<?> constructor : constructors) { if (constructor.getParameterCount() == 0) { return AUTOWIRE_BY_TYPE; } } return AUTOWIRE_CONSTRUCTOR; } else { return this.autowireMode; } }
再AbstractBeanDefinition的直接子类:
ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition、AnnotatedBeanDefinition
这四个的区别:
AnnotatedBeanDefinition
就是描叙通过注解的方式注入的BeanDefinition
RootBeanDefinition
看下RootBeanDefinition的注释:
A root bean definition represents the merged bean definition that backs ,a specific bean in a Spring BeanFactory at runtime。
用不太好的英语看下其主要意思。其是一个merged bean definition(合并的Bean定义),在BeanFactory at runtime(BeanFactory 运行使用的时候)。
我们看下BeanFactory在获取Bean的时候:
在AbstractBeanFactory通过Bean名称第一次获取对应Bean的getBean(String name)方法的过程中。是会调一个方法:
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
最后会调到这段代码
getMergedBeanDefinition( String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) { ..............
if (bd.getParentName() == null) {if (bd instanceof RootBeanDefinition) { mbd = ((RootBeanDefinition) bd).cloneBeanDefinition(); } else { mbd = new RootBeanDefinition(bd); } .......... } RootBeanDefinition(BeanDefinition original) { super(original); } protected AbstractBeanDefinition(BeanDefinition original) { setParentName(original.getParentName()); setBeanClassName(original.getBeanClassName()); setScope(original.getScope()); setAbstract(original.isAbstract()); setLazyInit(original.isLazyInit()); .......... }
也就是说,你在获取的Bean的时候,不管是哪种BeanDefinition的定义,如果不是RootBeanDefinition,都会转换为RootBeanDefinition。
ChildBeanDefinition
public class ChildBeanDefinition extends AbstractBeanDefinition { @Nullable private String parentName; ......... @Override public void setParentName(@Nullable String parentName) { this.parentName = parentName; } @Override @Nullable public String getParentName() { return this.parentName; } ........... }
其会有一个有父的BeanDefinition。而前面的RootBeanDefinition是没有parentName的(因为在获取Bean的时候其他的类型都是需要归并为RootBeanDefinition来最终使用):
public class RootBeanDefinition extends AbstractBeanDefinition { ...... @Override public String getParentName() { return null; } .......... }
我们再来看其在获取Bean的时候是怎样使用的(前面是走的bd.getParentName() == null的逻辑,现在走的是下面的内容):
if (bd.getParentName() == null) { ......... } else { BeanDefinition pbd; try { String parentBeanName = transformedBeanName(bd.getParentName()); if (!beanName.equals(parentBeanName)) { pbd = getMergedBeanDefinition(parentBeanName); } else { BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); } ............. mbd = new RootBeanDefinition(pbd); mbd.overrideFrom(bd); } }
这里的getMergedBeanDefinition就是会回到最初的获取MergedBean。这里就有有个循环调用。去获取父Bean,然后合并为RootBeanDefinition
GenericBeanDefinition
GenericBeanDefinition其也是有ParentName属性的。那这个GenericBeanDefinition与ChildrenBeanDefinitin的区别是什么呢?
其两者的区别主要是ChildrenBeanDefinitin没有子类了,而GenericBeanDefinition还有子类。(目前了解的使用情况:如果一个Bean有父Bean,Spring内部在使用BeanDefinition的时候也用的是这个GenericBeanDefinition,而ChildrenBeanDefinitin在Spring源码内部,Spring一般并没有主动去创建使用这个类)。
GenericBeanDefinition的子类:AnnotatedGenericBeanDefinition、ScannedGenericBeanDefinition
这两个子类一个是通过注解的方式注入的Bean、例如@Configuration等这种注直接指明一个对应的注解类注入的BeanDefinition就会装配为AnnotatedGenericBeanDefinition、而通过扫描包的方式其添加的BeanDefinition就会装配为ScannedGenericBeanDefinition。我们通过代码来说明:
AnnotatedGenericBeanDefinition:
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } ........... }
往上找这个方法的调用:
public void registerBean(Class<?> annotatedClass) { doRegisterBean(annotatedClass, null, null, null); } public class AnnotatedBeanDefinitionReader { ........ public void register(Class<?>... annotatedClasses) { for (Class<?> annotatedClass : annotatedClasses) { registerBean(annotatedClass); } ............ }
再找个调用此方法的测试demo:
@Test public void annotatedBeanDefinitionReader_inheritsEnvironmentFromEnvironmentCapableBDR() { GenericApplicationContext ctx = new GenericApplicationContext(); ctx.setEnvironment(prodEnv); new AnnotatedBeanDefinitionReader(ctx).register(Config.class); } @Configuration @Import({DevConfig.class, ProdConfig.class}) static class Config { @Bean public EnvironmentAwareBean envAwareBean() { return new EnvironmentAwareBean(); } }
ScannedGenericBeanDefinition
private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); ............ for (Resource resource : resources) { if (resource.isReadable()) { try { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); .......... }
@Test public void testSimpleScanWithDefaultFiltersAndPrimaryLazyBean() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.scan(BASE_PACKAGE); scanner.scan("org.springframework.context.annotation5"); .......... }
可以看到这个就是通过basePackage基本包,然后从对应包下面找到要注入的BeanDefinition会描叙为ScannedGenericBeanDefinition。
从成员变量的角度来说:
public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition { private final AnnotationMetadata metadata; @Nullable private MethodMetadata factoryMethodMetadata; ...... } public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition { private final AnnotationMetadata metadata; .......... }
AnnotatedGenericBeanDefinition 比ScannedGenericBeanDefinition 多了一个MethodMetadata :
public interface MethodMetadata extends AnnotatedTypeMetadata { String getMethodName(); String getDeclaringClassName(); String getReturnTypeName(); boolean isAbstract(); boolean isStatic(); boolean isFinal(); boolean isOverridable(); }
ConfigurationClassBeanDefinition:
class ConfigurationClassBeanDefinitionReader { .......... private static class ConfigurationClassBeanDefinition extends RootBeanDefinition implements AnnotatedBeanDefinition { private final AnnotationMetadata annotationMetadata; private final MethodMetadata factoryMethodMetadata; ........... }
可以看到其是定义在ConfigurationClassBeanDefinitionReader
那这个ConfigurationClassBeanDefinition是用来描叙哪种类型的BeanDefinition的呢。我们看下其的使用demo:
public static void main(String[] args) { GenericApplicationContext listableBeanFactory = new GenericApplicationContext(); new AnnotatedBeanDefinitionReader(listableBeanFactory).register(Config.class); listableBeanFactory.refresh(); TestBean bean = listableBeanFactory.getBean(TestBean.class); }
@Configuration public class Config { @Bean public TestBean getTestBean() { return new TestBean(); } }
可以看到通过在@Configuration 中使用@Bean会将其注册为ConfigurationClassBeanDefinition。而@Configuration是注册为前面讲的AnnotatedGenericBeanDefinition: