实习成长之路——SpringBean一:BeanDefinition元信息有什么?除了Bean名称和类型,还有那些Bean的元信息值得关注?

BeanDefinition元信息有哪些信息?

这里放小马老师的一张图
在这里插入图片描述
在我刚开始学习Spring的时候,还是XML方式来配置的,所以大概都知道什么意思,一般我们都BeanDefinition一般通过XML方式配置的比较多一点
下面看看BeanDefinition的构建

BeanDefinition的构建

  1. 通过BeanDefinitionBuilder
  2. 通过AbstractBeanDefinition以及派生类
/**
 * @ClassName BeanDefinitionCreationDemo
 * @Description
 * @Author huacheng
 * @Date 2021/9/21 4:31 下午
 * @Version 1.0
 **/
public class BeanDefinitionCreationDemo {
    public static void main(String[] args) {
        //1.通过BeanDefinitionBuilder
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        //通过属性设置操作
//        public BeanDefinitionBuilder addPropertyValue(String name, @Nullable Object value) {
//            this.beanDefinition.getPropertyValues().add(name, value);
//            return this;
//        }
        beanDefinitionBuilder.addPropertyValue("name","小王");//等同于XML配置方式
        beanDefinitionBuilder.addPropertyValue("age",18);
        //获取BeanDefinition实例
        BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        //这里只是生成了一个Bean的定义,我们还是可以做修改操作的
        //并非是Bean的最终态,可以自定义修改
        System.out.println(beanDefinition);


        //2。通过AbstractBeanDefinition 以及派生构建
        //genericBeanDefinition源码new了GenericBeanDefinition,那么我们就可以通过它来获取
//        public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) {
//            BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new GenericBeanDefinition());
//            builder.beanDefinition.setBeanClass(beanClass);
//            return builder;
//        }
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        genericBeanDefinition.setBeanClass(User.class);
        //    public void setPropertyValues(MutablePropertyValues propertyValues) {
        //        this.propertyValues = propertyValues;
        //    }
        //通过MutablePropertyValues 批量操作属性
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        //    public void addPropertyValue(String propertyName, Object propertyValue) {
        //        this.addPropertyValue(new PropertyValue(propertyName, propertyValue));  跟上面add实际上是一样的
        //    }
        propertyValues.addPropertyValue("name","小王");
        propertyValues.addPropertyValue("age",30);
        propertyValues.add("name","小王").add("age",30);
        genericBeanDefinition.setPropertyValues(propertyValues);
        System.out.println(genericBeanDefinition);

    }
}

运行结果

Generic bean: class [com.huacheng.ioc.dependency.lookup.domain.User]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
Generic bean: class [com.huacheng.ioc.dependency.lookup.domain.User]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null

我们可以看到是一样的

怎么命名Spring Bean

每个Bean拥有一个或者多个识别符(identifiers),这些标识符在 Bean 所在的容器必须是 唯一的。通常,一个 Bean 仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来 扩充。

注:并不是应用里面唯一

在基于 XML 的配置元信息中,开发人员可用 id 或者 name 属性来规定 Bean 的 标识符。通 常 Bean 的 标识符由字母组成,允许出现特殊字符。如果要想引入 Bean 的别名的话,可在 name 属性使用半角逗号(“,”)或分号(“;”) 来间隔。

Bean 的 id 或 name 属性并非必须制定,如果留空的话,容器会为 Bean 自动生成一个唯一 的名称。Bean 的命名尽管没有限制,不过官方建议采用驼峰的方式,更符合 Java 的命名约 定。

Bean 名称生成器(BeanNameGenerator)
由 Spring Framework 2.0.3 引入,框架內建两种实现:
DefaultBeanNameGenerator:默认通用 BeanNameGenerator 实现

AnnotationBeanNameGenerator:基于注解扫描的 BeanNameGenerator 实现,起始于 Spring Framework 2.5

public interface BeanNameGenerator {
    String generateBeanName(BeanDefinition var1, BeanDefinitionRegistry var2);
}

一个参数是Bean定义,一个是Bean定义的注册中心
我们看看它的第一个实现

public class DefaultBeanNameGenerator implements BeanNameGenerator {
    public static final DefaultBeanNameGenerator INSTANCE = new DefaultBeanNameGenerator();

    public DefaultBeanNameGenerator() {
    }

    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
    }
}

为什么这个地方没有把构造器写成私有的呢?
因为DefaultBeanNameGenerator是一个公有API,如果擅自在高版本中,把他的构造函数改成非public的话,其他版本就会不兼容

 public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        return generateBeanName(beanDefinition, registry, false);
    }

    public static String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean) throws BeanDefinitionStoreException {
    //先取BeanClassName
        String generatedBeanName = definition.getBeanClassName();
        if (generatedBeanName == null) {
            if (definition.getParentName() != null) {
                generatedBeanName = definition.getParentName() + "$child";
            } else if (definition.getFactoryBeanName() != null) {
                generatedBeanName = definition.getFactoryBeanName() + "$created";
            }
        }

        if (!StringUtils.hasText(generatedBeanName)) {
            throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither 'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
        } else if (isInnerBean) {//内嵌Bean,会生成一个#号
            String id = generatedBeanName + "#" + ObjectUtils.getIdentityHexString(definition);
            return id;
        } else {//唯一Bean,也会拼接一个#,加一个数字,数字从0开始逐一叠加
            return uniqueBeanName(generatedBeanName, registry);
        }
    }

注解实现

public class AnnotationBeanNameGenerator implements BeanNameGenerator {
    public static final AnnotationBeanNameGenerator INSTANCE = new AnnotationBeanNameGenerator();
    private static final String COMPONENT_ANNOTATION_CLASSNAME = "org.springframework.stereotype.Component";

    public AnnotationBeanNameGenerator() {
    }

    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        if (definition instanceof AnnotatedBeanDefinition) {//如果是注解标注
            String beanName = this.determineBeanNameFromAnnotation((AnnotatedBeanDefinition)definition);
            if (StringUtils.hasText(beanName)) {
                return beanName;
            }
        }
//传统方式的兼容
        return this.buildDefaultBeanName(definition, registry);
    }
    

Bean的别名

Bean 别名(Alias)的价值
• 复用现有的 BeanDefinition
• 更具有场景化的命名方法,比如:

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/> 
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>

在这里插入图片描述

在这里插入图片描述
定制别名

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会写代码的花城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值