在Spring中,beanDefinition加载后会被放置beanDefinitionMap,当Spring容器进行bean对象创建时,这个过程中会先进行beanDefinition的合并;
对于单例对象流程大致如下:
AbstractBeanFactory#doGetBean
在进行bean对象创建前会先进行beanDefinition的合并操作;
对于子beanDefinition是可以继承父beanDefinition的;
例子如下:
将父beanDefinition设置为多例类型;
@Test public void childBeanDefinitionTest1() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // 作为一个父类,也可以是一个普通类 RootBeanDefinition beanADefinition = new RootBeanDefinition(BeanA.class); beanADefinition.setScope(AbstractBeanDefinition.SCOPE_PROTOTYPE); ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("beanA"); childBeanDefinition.setBeanClass(BeanB.class); context.registerBeanDefinition("beanA", beanADefinition); context.registerBeanDefinition("beanB", childBeanDefinition); context.refresh(); }
此时BeanA,BeanB都没有被实例化,BeanA的beanDefinition的scope为prototype类型,说明BeanA的beanBeanDefinition被BeanB的beanDefinition继承了;
从上面的例子可以看出,beanDefinition具有继承性;
例子如下:
将子beanDefinition设置为多例类型;
@Test public void childBeanDefinitionTest1() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // 作为一个父类,也可以是一个普通类 RootBeanDefinition beanADefinition = new RootBeanDefinition(BeanA.class); ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("beanA"); childBeanDefinition.setBeanClass(BeanB.class); childBeanDefinition.setScope(AbstractBeanDefinition.SCOPE_PROTOTYPE); context.registerBeanDefinition("beanA", beanADefinition); context.registerBeanDefinition("beanB", childBeanDefinition); context.refresh(); }
此时只有一个BeanA进行实例化,BeanA的beanDefinition作为父beanDefinition,默认为单例,BeanB的beanDefinition设置为多例,因此BeanB不能被显示实例化;
getMergedLocalBeanDefinition最终会调用到下面方法;
AbstractBeanFactory#getMergedBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.config.BeanDefinition)
而对于beanDefinition为parent类型的会执行cloneBeanDefinition方法,clone意思是克隆,常见于原型模式,如下:
而这个this表示原始的beanDefinition,beanDefinitionMap中的beanDefinition;
为何需要进行beanDefinition合并的操作?
对于Spring来说,spring不知道当前bean的beanDefinition是否存在继承,因此父子beanDefinition都需要进行merge操作;