目录
1. IOC发生的时间
一般情况,依赖注入发生在第一次向容器(BeanFactory或ApplicationContext)索要bean时,即调用getBean方法。
特别情况,通过设置bean的lazy-init属性=false执行预实例化,与一般情况相比,只是发生的时间不同,还是通过getBean方法触发。
2. XmlBeanFactory的UML
DefaultSingletonBeanRegistry类的几个重要属性:
Map<String, Object> singletonObjects(一级缓存):单例对象的缓存
Map<String, Object> earlySingletonObjects(二级缓存):早期(early)单例对象的缓存
Map<String, ObjectFactory<?>> singletonFactories(三级缓存):单例工厂的缓存
Set<String> singletonsCurrentlyInCreation:当前在创建中的单例bean name
FactoryBeanRegistrySupport类的缓存属性:
Map<String, Object> factoryBeanObjectCache:键是factoryBean name,值是factoryBean创建的对象
3. getBean方法的主要逻辑
scope=singleton时,逻辑如下:
byType装配依赖的逻辑较为复杂,部分代码解读如下:
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//对于java容器类属性,autowiredBeanNames存储元素类型匹配的所有beanNames,
//对于非java容器类属性,autowiredBeanNames只存了1个元素
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//找出需要被注入属性值的属性名称
//不需要注入的情况:属性的写方法是cglib方法&未被超类声明、属性是指定忽略的类型(or接口实现)、
//属性的值已经在beanDefinition中指定、属性是简单类型、属性是arry但元素是简单类型
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//获取属性的描述,会递归解析嵌套属性
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
//不会尝试对Object类型自动装配,即使它是unsatisfied & 非简单属性
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
//是否可以立即处理:实现了PriorityOrdered接口不可以立即处理
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//🔽进入下层方法
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//(🔽进入下层方法)一般情况,其它分支不满足,执行这部分逻辑
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//设置当前依赖注入点,返回前一个依赖注入点,finally语句又恢复设置.?不确定如此设计的原因?
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
// 支持注解@value?xml文件配置返回null
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 对集合、map、数组、stream等java容器类型解析
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//1.按类型匹配找出所有的「候选beanName」
// 1.1 遍历beanFactory中的List<String> beanDefinitionNames:
// 1.1.1 根据是否实例化、beanDefinition判断类型是否匹配,存入List<String>
//2.遍历「候选beanName」,跳过autowire-candidate="false"的beanName
// 2.1 如果候选bean未实例化,按键=候选beanName、值=候选bean类型
// 如果已实例化,按键=beanName、值=bean实例,存入Map<String, Object>
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 决定策略:是否primary、最高优先级、兜底(遍历返回第一个满足的)
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// 只有1个
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
//调用beanFactory的getBean(...)方法
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
参考资料
《spring技术内幕》