Spring | Bean基础 (一)

在本文总结Spring Bean的部分基础内容,首先会总结BeanDefinition的职责;在了解BeanDefinition是做什么之后,再进一步总结BeanDefinition的层级结构,即总结其扩展哪些类,以及实现类;在上面基础上,进一步通过代码总结如何去注册BeanDefinition,以及如何使用BeanDefinition去生成一个Bean。

BeanDefinition Class

BeanDefinition是Spring Framework中定义Bean的配置元信息接口,描述一个bean实例应该具有属性值和方法特征(设置Bean的class name、scope、lazyInit等) 。注意,这只是一个最小的接口:主要目的是允许BeanFactoryPostProcessor缺省处理(introspect)[1]和修改属性值和其他bean元数据。

BeanDefinition 层级

通过Spring API文档可以查询BeanDefinition的层级结构,如下图所示,

将结构转化成UML进行展示,

Interface AttributeAccessor

该接口定义一个用于向任意对象附加和访问元数据的通用契约。

Interface BeanMetadataElement

定义一个bean metadata 的实现应该携带获取configuration source 对象行为的契约

Class AbstractBeanDefinition

具体的、成熟的BeanDefinition类的基类,提取出GenericBeanDefinition、RootBeanDefinition和ChildBeanDefinition的公共属性。autowire常数与在AutowireCapableBeanFactory接口中定义的常数匹配。

Interface AnnotatedBeanDefinition

扩展的BeanDefinition接口,它公开关于其bean类的注释元数据。

Class RootBeanDefinition

根bean定义表示在运行时支持Spring BeanFactory中的特定bean的合并bean定义。它可能是从相互继承的多个原始bean定义创建的,通常注册为GenericBeanDefinitions。根bean定义本质上是运行时的“统一”bean定义视图。根bean定义还可以用于在配置阶段注册单个bean定义。但是,自从spring2.5以来,通过编程注册bean定义的首选方法是使用GenericBeanDefinition类。GenericBeanDefinition的优点是,它允许动态定义父依赖项,而不是将角色“硬编码”为根bean定义。

Class ChildBeanDefinition

从父Bean继承设置的Bean定义。子bean定义对父bean定义有固定的依赖关系。子bean定义将从父bean继承构造函数参数值、属性值和方法覆盖,并具有添加新值的选项。如果指定了init方法、destroy方法和/或静态工厂方法,它们将覆盖相应的父设置。其余的设置将始终从子定义中获取:依赖、自动装配模式、依赖检查、单例、延迟init。

Class GenericBeanDefinition

GenericBeanDefinition是用于标准bean定义目的的一站式商店。与任何bean定义一样,它允许指定类以及可选的构造函数参数值和属性值。此外,可以通过“parentName”属性灵活地配置从父bean定义派生的内容。通常,使用这个GenericBeanDefinition类来注册用户可见的bean定义(后处理程序可能对其进行操作,甚至可能重新配置父名称)。如果父/子关系是预先确定的,请使用RootBeanDefinition / ChildBeanDefinition。

Class ScannedGenericBeanDefinition

对GenericBeanDefinition类的扩展,基于ASM类阅读器,支持通过AnnotatedBeanDefinition接口公开的注释元数据。

Class AnnotatedGenericBeanDefinition

对GenericBeanDefinition类的扩展,添加对通过AnnotatedBeanDefinition接口公开的注释元数据的支持。

进一步了解BeanDefinition

Bean元信息

Bean元信息有描述其类,作用域,属性值等信息,通过AbstractBeanDefinition.class 可以发现通用的Beans元信息

创建BeanDefinition

有两种方法构建一个BeanDefinition,一是通过BeanDefinitionBuilder,二是通过AbstractBeanDefinition派生类

 public static void main(String[] args) {
        // 1.通过 BeanDefinitionBuilder 构建
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition("testBean");
        beanDefinitionBuilder
                .addPropertyValue("msg", "hello world")
                .addPropertyValue("describe", "this is a test bean");
        // 获取 BeanDefinition 实例
        BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        System.out.println(beanDefinition.toString());

        // 2. 通过 AbstractBeanDefinition的衍生类构建,此处举例通过GenericBeanDefinition来构建BeanDefinition
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        genericBeanDefinition.setBeanClass(User.class);
        // 通过 MutablePropertyValues 批量操作属性
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        propertyValues.add("id", 123)
                .add("name", "Jany")
                .add("age", 18);
        genericBeanDefinition.setPropertyValues(propertyValues);
        System.out.println(genericBeanDefinition.toString());
    }

注册BeanDefinition

注册BeanDefinition有三种方式,
1.xml配置
2.注解配置
3.API配置

这里演示API配置和注解配置的方式
API配置:

/**
 * BeanDefinition 注册
 * 通过创建BeanDefinitionBuilder创建BeanDefinition,然后注册成Bean 注册
 * API配置
 */
public class Learn2 {
    public static void main(String[] args) {
        //通过BeanDefinitionBuilder创建BeanDefinition
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition("com.example.learnbean.entity.User");
        beanDefinitionBuilder
                .addPropertyValue("name", "Jane")
                .addPropertyValue("age", 18)
                .addPropertyValue("id", 31321);
        BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();

        // 创建 BeanFactory 容器
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        // 根据beanDefinition注册成spring bean
        applicationContext.registerBeanDefinition("testBean", beanDefinition);
        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 根据bean name 查找Bean
        System.out.println(applicationContext.getBean("testBean").toString());
        // 显示地关闭 Spring 应用上下文
        applicationContext.close();
    }
}

注解配置:

/**
 * BeanDefinition 注册
 * Java注解配置
 */
// 3. 通过 @Import 来进行导入
@Import(Learn2ch3.Config.class)
public class Learn2ch3 {
    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类)
        applicationContext.register(Learn2ch3.class);
        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 按照类型依赖查找
        System.out.println(applicationContext.getBeansOfType(User.class));
        System.out.println(applicationContext.getBeansOfType(Config.class));
        // 显示地关闭 Spring 应用上下文
        applicationContext.close();
    }

    // 2. 通过 @Component 方式
    @Component// 定义当前类作为 Spring Bean
    public class Config {
        // 1. 通过 @Bean 方式定义
        @Bean
        public User user() {
            User user = new User();
            user.setAge(18);
            user.setName("Jany");
            user.setId(123123);
            return user;
        }
    }
}
posted @ 2020-11-22 22:23  听说这是最长的名字了  阅读(143)  评论(0编辑  收藏  举报