zoukankan      html  css  js  c++  java
  • Spring bean name 怎么来的?

    sping的生命周期大概是这样的(生命周期),当然这个看也是看了个寂寞,看不出BeanName是怎么来。下面且看我细细道来。

    spring刷新容器的整个过程分为下面这若干步骤:

    @Override
    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    				...
                    // 生成bean name 在这一大步骤里面
    				invokeBeanFactoryPostProcessors(beanFactory);
    				...
    		}
    	}
    

    下面看一下函数调用栈:可以看到就是解析的时候生成bean name的

    下面看一下具体方法:

    @Override
    	public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    		if (definition instanceof AnnotatedBeanDefinition) {
    			String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
    			if (StringUtils.hasText(beanName)) {
    				// Explicit bean name found.
    				return beanName;
    			}
    		}
    		// Fallback: generate a unique default bean name.
    		return buildDefaultBeanName(definition, registry);
    	}
    

    从代码可以看出来如果自己指定了bean name 就用指定的名字,如果没有指定就用默认的策略生成bean name

    下面是获取获取指定的bean name

    protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
    		AnnotationMetadata amd = annotatedDef.getMetadata();
    		Set<String> types = amd.getAnnotationTypes();
    		String beanName = null;
    		for (String type : types) {
    			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
    			if (attributes != null) {
    				Set<String> metaTypes = this.metaAnnotationTypesCache.computeIfAbsent(type, key -> {
    					Set<String> result = amd.getMetaAnnotationTypes(key);
    					return (result.isEmpty() ? Collections.emptySet() : result);
    				});
    				if (isStereotypeWithNameValue(type, metaTypes, attributes)) {
    					Object value = attributes.get("value");
    					if (value instanceof String) {
    						String strVal = (String) value;
    						if (StringUtils.hasLength(strVal)) {
    							if (beanName != null && !strVal.equals(beanName)) {
    								throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
    										"component names: '" + beanName + "' versus '" + strVal + "'");
    							}
    							beanName = strVal;
    						}
    					}
    				}
    			}
    		}
    		return beanName;
    	}
    

    下面是默认的策略生成bean name:

    protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    		return buildDefaultBeanName(definition);
    	}
    

    继续往里面看:就是获取全限定类名,再获取类名进行处理

    protected String buildDefaultBeanName(BeanDefinition definition) {
    		String beanClassName = definition.getBeanClassName();
    		Assert.state(beanClassName != null, "No bean class name set");
    		String shortClassName = ClassUtils.getShortName(beanClassName);
    		return Introspector.decapitalize(shortClassName);
    	}
    

    从下面的代码可以看出有两种情况:

    如果类名的长度大于1,且前两个字母都是大写,那么bean name就是 类名,否则就是bean name 将类名首字母变小写

    public static String decapitalize(String name) {
            if (name == null || name.length() == 0) {
                return name;
            }
            if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                            Character.isUpperCase(name.charAt(0))){
                return name;
            }
            char[] chars = name.toCharArray();
            chars[0] = Character.toLowerCase(chars[0]);
            return new String(chars);
        }
    
  • 相关阅读:
    水仙花数 题解
    数值统计 题解
    平方和和立方和 题解
    第几天? 题解
    Python网络爬虫——http和https协议
    Python网络爬虫——爬虫简介
    python学习——pandas的拼接操作
    python学习——pandas层次化索引
    python学习——pandas扩展:傅里叶变换
    python学习——pandas数据丢失处理
  • 原文地址:https://www.cnblogs.com/d9e84208/p/15511087.html
Copyright © 2011-2022 走看看