spring中@Component属于最常使用的注解之一了,我们都知道,如果没有给定值得情况下,@Component默认值为该类首字母小写的类名,例如如下:
@Component
public class TargetFoo {
public void method1() {
}
}
如上类他的默认名就为targetFoo,那他这个默认值究竟是从哪里来的呢?源码里面可以找到对应的答案。
关键类就是AnnotationBeanNameGenerator中的如下代码:
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);
}
/**
* Derive a default bean name from the given bean definition.
* <p>The default implementation simply builds a decapitalized version
* of the short class name: e.g. "mypackage.MyJdbcDao" -> "myJdbcDao".
* <p>Note that inner classes will thus have names of the form
* "outerClassName.InnerClassName", which because of the period in the
* name may be an issue if you are autowiring by name.
* @param definition the bean definition to build a bean name for
* @return the default bean name (never {@code null})
*/
protected String buildDefaultBeanName(BeanDefinition definition) {
String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
return Introspector.decapitalize(shortClassName);
}
其实在这里buildDefaultBeanName方法的doc注释已经很说的很清楚了,举例如果一个bean类名为:"mypackage.MyJdbcDao" 那么通过这个方法,返回值就会变为"myJdbcDao"。如果你还好奇的点进去,能看到其具体实现,在这里要注意,如果是内部类则,外部类的名称不能省略,及"outerClassName.InnerClassName"不能变成"innerClassName".
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);
}