3.AbstractBeanDefinition的三个子类
GenericBeanDefinition
- 替代了原来的ChildBeanDefinition,比起ChildBeanDefinition更为灵活,ChildBeanDefinition在实例化的时候必须要指定一个parentName,而GenericBeanDefinition不需要。我们通过注解配置的bean以及我们的配置类(除@Bena外)的BeanDefiniton类型都是GenericBeanDefinition。
ChildBeanDefinition
- 现在已经被GenericBeanDefinition所替代了。我在5.1.x版本没有找到使用这个类的代码。
RootBeanDefinition
- Spring在启动时会实例化几个初始化的BeanDefinition,这几个BeanDefinition的类型都为RootBeanDefinition
- Spring在合并BeanDefinition返回的都是RootBeanDefinition
- 我们通过@Bean注解配置的bean,解析出来的BeanDefinition都是RootBeanDefinition(实际上是其子类ConfigurationClassBeanDefinition)
4.AnnotatedBeanDefinition
这个接口继承了我们的BeanDefinition接口,我们查看其源码可以发现:
AnnotationMetadata getMetadata(); @Nullable MethodMetadata getFactoryMethodMetadata();
这个接口相比于BeanDefinition, 仅仅多提供了两个方法
- getMetadata(),主要用于获取注解元素据。从接口的命名上我们也能看出,这类主要用于保存通过注解方式定义的bean所对应的BeanDefinition。所以它多提供了一个关于获取注解信息的方法
- getFactoryMethodMetadata(),这个方法跟我们的@Bean注解相关。当我们在一个配置类中使用了@Bean注解时,被@Bean注解标记的方法,就被解析成了FactoryMethodMetadata。
5.AnnotatedBeanDefinition的三个实现类
AnnotatedGenericBeanDefinition
- 通过形如下面的API注册的bean都是AnnotatedGenericBeanDefinition
public static void main(String[] args) { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(); ac.register(Config.class); }
这里的config对象,最后在Spring容器中就是一个AnnotatedGenericBeanDefinition。
- 通过@Import注解导入的类,最后都是解析为AnnotatedGenericBeanDefinition。
ScannedGenericBeanDefinition
- 都过注解扫描的类,如@Service,@Compent等方式配置的Bean都是
ScannedGenericBeanDefinition
ConfigurationClassBeanDefinition
- 通过@Bean的方式配置的Bean为ConfigurationClassBeanDefinition
最后,我们还剩一个ClassDerivedBeanDefinition,这个类是跟kotlin相关的类,一般用不到,笔者也不熟,这里就不管了!
总结
至此,我们算完成了BeanDefinition部分的学习,在下一节中,我将继续跟大家一起学习BeanDefinition合并的相关知识。这篇文章中,主要学习了
1.什么是BeanDefinition,总结起来就是一句话,Spring创建bean时的建模对象。
2.BeanDefinition的具体使用的子类,以及Spring在哪些地方使用到了它们。这部分内容在后面的学习中很重要,画图总结如下:
1.5小结内容的补充
单例
一个单例的bean意味着,这个bean只会容器创建一次。在创建后,容器中的每个地方使用的都是同一个bean对象。这里用Spring官网上的一个原图:
在上面图片的例子中,accountDao在被其它三个bean引用,这三个引用指向的都是同一个bean。
在默认情况下,Spring中bean的默认域就是单例的。分XML跟注解两种配置方式:
<!--即使配置singleton也是单例的,这是Spring的默认配置--> <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
@Component // 这里配置singleton,默认就是singleton @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) public class LuBanService{ }
原型
一个原型的bean意味着,每次我们使用时都会重新创建这个bean。
在上面图片的例子中,accountDao在被其它三个bean引用,这三个引用指向的都是一个新建的bean。
两种配置方式:
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
@Component // 这里配置prototype @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class LuBanService{ }