spring源码:bean加载之转换对应的beanName

一、目的

  spring中加载bean的一种方式,是用户主动调用BeanFactory#getBean(java.lang.String, java.lang.Class)方法。如下:

BeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
Person myPerson = xmlBeanFactory.getBean("myPerson", Person.class);

  BeanFactory是一个接口,该getBean方法由AbstractBeanFactory实现。该getBean()方法的第一步就是,转换对应的beanName。其目的是为了,把用户传入的name,解析为bean实例对应真正的beanName。供后面直接从DefaultListableBeanFactory#beanDefinitionMap中读取beanName对应的BeanDefinition信息,进而实例化该bean实例。有两种场景需要转换用户传入的name:

  1. 用户传入的name以&开头
    对于实现FactoryBean接口的类MyFactoryBean
    public class MyFactoryBean implements FactoryBean<Person> {
    	@Override
    	public Person getObject() throws Exception {
    		Person person = new Person();
    		person.setName("factoryBean");
    		return person;
    	}
    
    	@Override
    	public Class<?> getObjectType() {
    		return Person.class;
    	}
    }
    
    xml配置形如
    <bean id="myPerson" class="com.kaka.spring.pojo.MyFactoryBean" />
    
    // 默认情况下,获取的不是MyFactoryBean本身,而是MyFactoryBean的getObject()方法返回的实例
    Person myPerson = xmlBeanFactory.getBean("myPerson", Person.class);
    // 想要获取MyFactoryBean本身,需要加上一个&前缀
    MyFactoryBean bean = xmlBeanFactory.getBean("&myPerson", MyFactoryBean.class);
    
    对于获取MyFactoryBean本身的场景,就需要去掉&前缀,来获取真实的beanName
  2. 如果用户传入的name是bean的别名,则需要从SimpleAliasRegistry#aliasMap中获取对应的真实beanName

二、相关类及方法

  • org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean:加载bean的整体过程
  • org.springframework.beans.factory.BeanFactoryUtils#transformedBeanName:去掉name中的&前缀
  • org.springframework.core.SimpleAliasRegistry#canonicalName:获取别名对应的beanName

三、源码分析

  1. 加载bean的整体流程:AbstractBeanFactory#getBean
	public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		// 就看这第一步,转化对应的beanName
		final String beanName = transformedBeanName(name);
		// 忽略后续步骤
		...
	}
  1. 去掉name中的&前缀:BeanFactoryUtils#transformedBeanName
	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		String beanName = name;
		while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
		}
		return beanName;
	}
  1. 从SimpleAliasRegistry#aliasMap中,获取别名对应的beanName:SimpleAliasRegistry#canonicalName
	public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

综上处理,用户就获取到了指定bean的真实beanName;然后进行后面,实例化bean的步骤。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值