各BeanDefinition
实现类使用注意事项
一般使用建议
一般情况下,建议使用GenericBeanDefinition
用于定义用户可见的bean
定义。而对于一些父子关系已经确定的情况,使用RootBeanDefinition
/ChildBeanDefinition
。
各个实现类的区别/特点
RootBeanDefinition
– 不能设置parent bean
定义
由此可见,
RootBeanDefinition
不能用于用于父子bean
定义关系中的"子bean
定义"
ChildBeanDefinition
– 必须设置parent bean
定义,而且必须是通过构造函数指定
ChildBeanDefinition
很适合父子bean
定义关系明确的情况下基于双亲bean
定义和自身少量设置一些个性化属性从而进行子bean
定义。
实际上,真正在创建子bean
定义规定的bean
对象时,Spring
框架内部是将双亲bean
定义和孩子bean
定义合并形成一个最终使用的RootBeanDefinition
,这里孩子bean
定义中设置的属性会被优先使用,没有指定的都会继承使用双亲bean
定义中的设置。
GenericBeanDefinition
– 可以动态设置parent bean
定义,也可以不设置parent bean
定义
由此可见,
GenericBeanDefinition
既可以替代RootBeanDefinition
,也可以替代ChildBeanDefinition
,所以GenericBeanDefinition
更一般化(generic
)
演示源码
辅助演示使用的bean
类
package tut.zero;
import lombok.Data;
@Data
public class Pet {
String type;
String name;
}
演示BeanDefinition
各个实现类例如何被使用
package tut.zero;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.ChildBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Properties;
@Slf4j
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
AnnotationConfigApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... args) {
// RootBeanDefinition
demoRootBeanDefinition();
// ChildBeanDefinition
demoChildBeanDefinition();
// GenericBeanDefinition
demoGenericBeanDefinition();
}
private void demoRootBeanDefinition() {
// 此例子演示 RootBeanDefinition 的使用,通过它,提供了创建一个 bean 所需
// 的所有信息
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setBeanClass(Pet.class);
rbd.getPropertyValues().add("type", "dog");
rbd.getPropertyValues().add("name", "Jack");
applicationContext.registerBeanDefinition("rootPetDog", rbd);
Pet pet = (Pet) applicationContext.getBean("rootPetDog");
log.info("Parent pet dog is :{}", pet);
}
private void demoChildBeanDefinition() {
// 创建一个 ChildBeanDefinition 总是要依赖于另外一个 bean定义,也就是该孩子 bean定义的双亲bean定义
// 此例子演示 ChildBeanDefinition 的使用,该例子中,所创建的 ChildBeanDefinition 使用了上面定义的名
// 为rootPet的 RootBeanDefinition。
// 实际上 ChildBeanDefinition 的双亲parent bean定义的类型不必要是 RootBeanDefinition,也可以是
// ChildBeanDefinition 或者 GenericBeanDefinition
ChildBeanDefinition cbd = new ChildBeanDefinition("rootPetDog");
cbd.getPropertyValues().add("name", "Little Jack");
applicationContext.registerBeanDefinition("childPetDog", cbd);
Object pet = applicationContext.getBean("childPetDog");
log.info("Child pet dog is :{}", pet);
// 从 Spring 2.5 之后,ChildBeanDefinition 被建议使用 GenericBeanDefinition 替换。
// 通过 GenericBeanDefinition 可以动态地设置双亲bean定义。
}
private void demoGenericBeanDefinition() {
// 这里演示 GenericBeanDefinition 的使用
// 基于 GenericBeanDefinition 的双亲bean定义
GenericBeanDefinition rbd = new GenericBeanDefinition();
rbd.setBeanClass(Pet.class);
rbd.getPropertyValues().add("type", "cat");
rbd.getPropertyValues().add("name", "Tom");
applicationContext.registerBeanDefinition("parentPetCat", rbd);
Pet petParent = (Pet) applicationContext.getBean("parentPetCat");
log.info("Parent pet cat is :{}", petParent);
// 基于 GenericBeanDefinition 的孩子bean定义
GenericBeanDefinition cbd = new GenericBeanDefinition();
cbd.setParentName("parentPetCat");
cbd.getPropertyValues().add("name", "Little Tom");
applicationContext.registerBeanDefinition("childPetCat", cbd);
Object petChild = applicationContext.getBean("childPetCat");
log.info("Child pet cat is :{}", petChild);
}
}
演示输出
Parent pet dog is :Pet(type=dog, name=Jack)
Child pet dog is :Pet(type=dog, name=Little Jack)
Parent pet cat is :Pet(type=cat, name=Tom)
Child pet cat is :Pet(type=cat, name=Little Tom)
从该输出可以看出:
- 对于子
bean
定义生成的bean
实例,优先采用子bean
定义中设置的属性,其他继承使用自双亲bean
定义。
相关文章
Spring的bean定义 1 : 基础建模–接口BeanDefinition
Spring的bean定义 2 : 通用bean定义逻辑 – AbstractBeanDefinition
Spring的bean定义 3 : BeanDefinition实现类例子演示
Spring的bean定义 4 : 合并了的bean定义–MergedBeanDefinition