• 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;
            }
        }
    }
    
  • 相关阅读:
    利用python数据分析与挖掘相关资料总结
    pandas库学习笔记(一)Series入门学习
    mysql error:You can't specify target table for update in FROM clause
    查询及删除重复记录的SQL语句
    PHP tripos()函数使用需要注意的问题
    如何用git上传代码到github详细步骤
    这是我的第一篇博客
    html link js
    BOM与DOM
    创建简单的表单
  • 原文地址:https://www.cnblogs.com/jj81/p/14011953.html
Copyright © 2020-2023  润新知