- 什么是依赖注入?
- 依赖注入用到了哪些技术?
- 依赖注入的时机?
- @Autowired原理?类型注入说明?
- 属性注入与依赖注入的区别
- @Autowired、@Value、@Resource 三者区别
- 根据名称注入与根据类型注入区别
- @Primary注解用法,作用
- @Priority注解用法,作用
入口Refresh()
依赖注入发生在Spring 容器的初始化过程中,先与解析再执行依赖注入
//注册AutoWriedAnnotaionBeanPostProcessor
registerBeanPostProcessors(beanFactory);
//初始化Bean
finishBeanFactoryInitialization(beanFactory);
//进入getBean()->doGetBean()->createBean()->doCreateBean()
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
/*省略代码*/
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed
//预解析
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//依赖注入
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
/*省略代码*/
}
预解析过程
预解析过程就是获取此Bean中的所有属性和方法,然后遍历判断是否有@Autowired、@Value、@Resource注解,最后生成InjectionMetadata类存储在缓存之中
1.通过class获取Bean中的所有字段和方法
2.遍历,执行回调函数findAutowiredAnnotation
3.判断是否有@Autowired注解和@Value注解,如果有进行存储List
4.最有根据class和List生产的InjectionMetadata
1.注册AutoWriedAnnotationBeanPostProcessor
2.Bean工厂通过getSingleton(beanName)判断Bean是否存在,存在则返回
3.实例化Bean,得到Bean的包装类 CglibSubclassingInstantiationStrategy 动态代理实例化包装类
4.实现注入元素的预解析:applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
findAutowiringMetadata(beanName, beanType, null)
获取InjectionMetadata类,此类中存储了当前Bean以及该Bean依赖的Bean(list)
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//如果缓存中没有则执行进行构建(遍历)
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
buildAutowiringMetadata()
获取该Bean的所有属性和方法判断是否有注解
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//存储该Bean的依赖的List
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//Fileds
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//method
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(