这里我们主要分析spring是怎么去根据类型或name去找值得。
方法参数的名字:加了@Autowired 注解的方法中的参数
字段:加了@Autowired的属性
DependencyDescriptor descriptor
descriptor可能是字段,也可能是方法的参数,需要根据descriptor来获取(字段或方法参数)的名字或类型。
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
上面这段代码主要是为了获取方法参数的名字。
1
2
3
4
addDiscoverer(new StandardReflectionParameterNameDiscoverer());
addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
这里初始化了两种获取方法参数的名字,一种是基于反射:主要是jdk1.8以上提供的方法。一种是基于本地变量表,主要是解决jdk1.7 没有通过反射可以获取方法参数名字的问题。
1.@Autowired+@Lazy
懒注入
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
上面这段代码就是处理@Lazy注解:
如果加了@Lazy注解 那么就会返回一个代理对象,将代理对象赋值给属性(方法参数)。当属性(方法参数)在调用方法的时候,spring才会去找bean。
2.@Value
处理@Value
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
这段代码是处理这种方式赋值:@Value(${"456"})
spring在最开始的时候会初始化一个Environment ,这个对象里面包含了spring.properties 配置文件中的key value 键值对.
@Value注解就是去Environment 对象中根据键找值。
value = evaluateBeanDefinitionString(strVal, bd);
这个是为了处理:@Value("#{person}")
这种是spring表达式,可以根据person 这个名字从spring容器中找bean 给属性赋值。
3.属性定义为:Map<String,Person> person
这种情况,spring会根据类型去找值,找到之后会将bean 的名字作为key, 值作为value 存入到map中。 这里map 的key 只能是string。
4.拿到符合类型的bean 或 beanClass
这里拿到的可能是bean对象,也可能是 beanClass。
如上面两个图,同一个类型(Company)的bean 有两个,名字不一样。那么获取的时候不管是创建好了对象,还是没创建好,都可以通过beanDefinition来判断是不是符合该类型。
如果判断是同类型,那么就会存到map中,在存的时候如果创建好就会存bean对象,如果没有创建好就会存beanClass。
5.1通过名字来进行匹配
如果是多个,这里会根据名字来进行匹配。 但是这里是有一个优先级的。顺序如下:
@Primary > @Primary(1)>name
5.2 处理根据类型获取单个bean 。
6.记录beanName
7.如果获取的是bean的类型 ,那就进行实例化
8.处理null
如上图所示 定义一个bean 返回null, 那么spring 在存的时候,会以com 为key , nullBean 为值:map<com,nullBean>