Spring的bean定义 3 : BeanDefinition实现类例子演示

56 篇文章 12 订阅
26 篇文章 3 订阅

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值