spring依赖注入
spring依赖注入
@Autowired、@Resource、@Value
@Resource、@Autowired、@Value 标注字段、方法,则表示需要依赖注入(就是反射给字段设置值、反射执行方法)
在依赖注入的前提上:
- 使用@Lazy则表示注入的是代理对象,执行代理对象时才会真正进行依赖的解析
- 使用@Qualifier("beanName"),匹配了多个注入的值时,遍历每个候选者,找到限定beanName一致的候选者
- 使用@Primary,匹配了多个注入的值时,有@Primary的候选者作为最终的注入值
- 使用@Priority,匹配了多个注入的值时,然后没有@Primary的候选者,才会根据@Priority的排序值,找到至最小的作为最终的注入值
注:匹配了多个注入的值时,没有@Qualifier、@Primary、@Primary限定,那就根据字段的名字、或者方法的参数名作为限定名匹配候选者
// 准备一个带泛型的Bean
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class GenericBean<T, W> {
private T t;
private W w;
}
// config配置文件中注入两个泛型Bean
@Bean
public Parent parentOne() {
return new Parent();
}
@Bean
public Parent parentTwo() {
return new Parent();
}
@Bean
public GenericBean<String, String> stringGeneric() {
return new GenericBean<String, String>("str1", "str2");
}
@Bean
public GenericBean<Object, Object> objectGeneric() {
return new GenericBean<Object, Object>("obj1", 2);
}
// 使用@Autowired注入,测试一下:
@Autowired
private GenericBean<Object, Object> objectGenericBean; //GenericBean(t=obj1, w=2)
@Autowired
private GenericBean<String, String> stringGenericBean; //GenericBean(t=st r1, w=str2)
// 注意,容器里虽然有两个Parent,这里即使不使用@Qualifier也不会报错。
// 但是需要注意字段名parentOne,必须是容器里存在的,否则就报错了。
@Autowired
private Parent parentOne; //com.fsx.bean.Parent@23c98163
//Spring4.0后的新特性,这样会注入所有类型为(包括子类)GenericBean的Bean(但是顺序是不确定的,可通过Order接口控制顺序)
@Autowired
private List<GenericBean> genericBeans; //[GenericBean(t=st r1, w=str2), GenericBean(t=obj1, w=2)]
// 这里的key必须是String类型,把GenericBean类型的都拿出来了,beanName->Bean
@Autowired
private Map<String, GenericBean> genericBeanMap; //{stringGenericBean=GenericBean(t=st r1, w=str2), objectGenericBean=GenericBean(t=obj1, w=2)}
// 这里面,用上泛型也是好使的,就只会拿指定泛型的了
@Autowired
private Map<String, GenericBean<Object, Object>> genericBeanObjMap; //{objectGenericBean=GenericBean(t=obj1, w=2)}
// 普通类型,容器里面没有的Bean类型,注入是会报错的
//@Autowired
//private Integer normerValue;
循环依赖
/**
* 只有单例bean支持循环依赖,原型和Scope是不支持循环依赖的
* 看
* { AbstractBeanFactory的doGetBean(String, Clazz, Object[], boolean)}
* */
/**
* 循环依赖bean校验逻辑
* 看 { AbstractAutowireCapableBeanFactory的doCreateBean(String, RootBeanDefinition, Object[])}
*
* 这里是为了处理二级缓存中的bean 和 执行了初始化操作的 bean 不一致的校验,不一致说明可能存在
* 依赖注入的bean 和 实际存入单例池中的bean 不一致的问题。对于不一致,下面的处理是报错
*
*
* 比如 A 注入了 B,B 注入了 A
* 先是 getBean(A),然后其 populateBean 环节要注入B, 所以会 getBean(B),然后其 populateBean 环节要注入A,所以要 getBean(A)
* 此时发现A正在创建,所以会读取三级缓存的value,然后执行提前AOP得到一个 proxyBeanA ,并将 proxyBeanA 存入二级缓存,然后将 proxyBeanA 注入到 B中,
* 然后B就创建完了,然后B就会被注入到A中,所以A的 populateBean 结束了,然后会执行 initializeBean。假设在 initializeBean 生成了 proxyBeanA2 。
* 这就出现了 注入到B中的A,和实际最终生成的A不一致的问题,对于这中情况,只能直接报错了,下面的逻辑就是为了应付这种情况的,
*
* 注:当然 提前AOP 也不一定会创建代理对象,我这里只是举例了 提前AOP和初始化都创建了代理对象的场景,方便说明
* */
protected Object doCreateBean(String beanName, RootBeanDefinition mbd,
@Nullable Object[] args) throws BeanCreationException {
// 实例化bean
bean = createBeanInstance(beanName, mbd, args);
if (earlySingletonExposure) {
/**
* 循环依赖-添加到三级缓存中
* 把我们的早期对象包装成一个 singletonFactory 对象,该对象提供了一个 getObject方法,该方法内部调用 getEarlyBeanReference(beanName, mbd, bean)
* 实现提前AOP
* */
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
// 填充bean,就是依赖注入或者给属性设置值
populateBean(beanName, mbd, instanceWrapper); // getBean()
// 进行对象初始化操作(在这里可能生成代理对象)
exposedObject = initializeBean(beanName, exposedObject, mbd);
/**
* 这里是为了处理二级缓存中的bean 和 执行了初始化操作的 bean 不一致的校验,不一致说明可能存在
* 依赖注入的bean 和 实际存入单例池中的bean 不一致的问题。对于不一致,下面的处理是报错
*
*
* 比如 A 注入了 B,B 注入了 A
* 先是 getBean(A),然后其 populateBean 环节要注入B, 所以会 getBean(B),然后其 populateBean 环节要注入A,所以要 getBean(A)
* 此时发现A正在创建,所以会读取三级缓存的value,然后执行提前AOP得到一个 proxyBeanA ,并将 proxyBeanA 存入二级缓存,然后将 proxyBeanA 注入到 B中,
* 然后B就创建完了,然后B就会被注入到A中,所以A的 populateBean 结束了,然后会执行 initializeBean。假设在 initializeBean 生成了 proxyBeanA2 。
* 这就出现了 注入到B中的A,和实际最终生成的A不一致的问题,对于这中情况,只能直接报错了,下面的逻辑就是为了应付这种情况的,
*
* 注:当然 提前AOP 也不一定会创建代理对象,我这里只是举例了 提前AOP和初始化都创建了代理对象的场景,方便说明
*
* */
if (earlySingletonExposure) {
/**
* 去缓存中获取到我们的对象,由于传递的 allowEarlyReference 是false要求只能在一级二级缓存中去获取。
* 说白了,就尝试从二级缓存中获取bean。
*
* 注:在这里就能体会到三级缓存的好处了。因为这里是只会从一级缓存和二级缓存中获取内容(其实只可能从二级缓存中拿到,一级缓存是拿不到的,因为此时还未将单例bean存入一级缓存)
* 如果二级缓存拿到的值不为null,就校验一下 exposedObject(执行了初始化后置处理器返回的值) 和 bean(简单实例化出来的) 是否一致,
* 若不一致,就需要判断一下,这个bean是否注入给了其他bean对象,若注入给了其他bean对象,那么就只能报错了,因为已经注入给了其他bean的值 和 exposedObject 不一致。
*
* 假设我们采用二级缓存来解决循环依赖的问题。思路如下:
* 一级缓存用来缓存最终完全的bean,二级缓存一开始存入的是 ObjectFactory ,当出现了循环依赖时,读取二级缓存的值,然后回调方法 ObjectFactory的getObject 得到 提前AOP的bean。
* 将 提前AOP的bean 存入进二级缓存,也就是进行值覆盖。
*
* 一级缓存:< beanName,最终的bean >
* 二级缓存:< beanName, ObjectFactory 或者 提前AOP得到的bean >
*
* 这就会出现一个问题,很难确定二级缓存存储得值 是 ObjectFactory 还是 提前AOP得到的bean,
* 你可能会这么想 `earlySingletonReference instanceof ObjectFactory` 来检验,但这是不靠谱的,因为有可能bean的类型就是 ObjectFactory 的
* 所以呢,只能使用东西标记二级缓存的值 是 ObjectFactory 还是 提前AOP得到的bean,
* 比如 这么设计: ThreadLocal< beanName, boolean > earlyLocal : false 表示二级缓存的值是 ObjectFactory,true 表示二级缓存的值是 提前AOP得到的bean
*
* 那么下面的 判断逻辑应当改成 ` if ( earlySingletonReference != null && earlyLocal.get().get(beanName) )
*
* 所以呢肯定是需要使用东西来标记一下,是否执行了 ObjectFactory 得到 提前AOP得到的bean,Spring是采用的三级缓存来标记,
* 这就是为啥使用三级缓存
*
* */
Object earlySingletonReference = getSingleton(beanName, false);
/**
* 能够获取到,说明是在二级缓存拿到的。也就是这个 beanName 产生了循环依赖的问题,
* */
/**
* 相等,说明初始化操作并没有对bean进行代理,那就没事。二级缓存的值作为最后要存入单例池中的值
* 不相等,说明对bean进行了代理。这就会导致循环依赖了bean的那些东西,注入的bean是不对的,我们需要判断一下
* 那些东西是否已经创建完了,创建完,那就没得搞了,只能报错了。
*/
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
/**
* hasDependentBean(beanName) 说明,这个bean已经注入到其他的bean对象中
* */
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
/**
* 获取依赖了 beanName 的bean。其实就是获取哪些bean注入了 beanName这个bean
*
* 在依赖注入时会记录,比如@Resource的注入逻辑 { org.springframework.context.annotation.CommonAnnotationBeanPostProcessor的autowireResource(BeanFactory, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.LookupElement, String)}
* */
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
/**
* 尝试挽救一下,如果 dependentBean 还没有创建完成,那就没问题了
*
* 创建完成的标记,是在这个地方设置的,也就是在 doGetBean 的一开始就设置了
* { AbstractBeanFactory的doGetBean(String, Clazz, Object[], boolean)}
* { AbstractBeanFactory的markBeanAsCreated(String)}
* */
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
/**
* 已经创建完了,就记录一下。
* */
actualDependentBeans.add(dependentBean);
}
}
// 报错
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException();
}
}
}
return exposedObject;
}
AutowiredAnnotationBeanPostProcessor
处理有
@Autowired | @Value
的字段、方法,进行依赖注入
@Autowired
推断构造器
@Lookup
标注的方法,记录到BeanDefinition中,在后面实例化bean的时候会创建代理对象
BeanPostProcessor执行过程:实例化前后置 -> 推断构造器后置(hit) --> 实例化bean -> 合并BeanDefinition后置(hit) -> 实例化后后置 -> 属性注入后置(hit )->初始化前后置 -> 初始化后后置 -> 销毁前后置
推断构造器阶段 AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors方法
作用一:解析类中(会递归解析父类)标注了@Lookup的方法,装饰成
new LookupOverride(method, lookup.value())
对象设置成BeanDefinition的属性。在实例化bean的时候,会获取该属性判断是否需要生成Cglib代理对象。推断构造器。
candidateConstructors = new Constructor<?>[0]; 存在@Autowired标注的构造器 @Autowired(required=true) 只能标注一个。candidateConstructors = [这一个] @Autowired(required=false) 可以标注多个。candidateConstructors = [多个+无参构造器(如果存在)] 不存在 只有一个构造器且是有参的。candidateConstructors = [这一个] return candidateConstructors.length>0 ? candidateConstructors : null 返回null,就是没有候选的构造器集合,后面的实例化自然会调用无参构造器实例化
合并BeanDefinition阶段
拿到bean的InjectionMetadata对象
- beanName 或者 beanClazz.getName 作为key,从缓存中{ AutowiredAnnotationBeanPostProcessor的injectionMetadataCache方法}取出InjectionMetadata
- InjectionMetadata 是空 或者需要刷新,就解析beanCass构建 InjectionMetadata 对象
- do...while 递归解析clazz及其所有父类,拿到其中标注了 @Autowired、@Value 的方法和字段构造成InjectedElement,然后记录在局部变量elements中
new AutowiredFieldElement(field, required)
new AutowiredMethodElement(method, required, pd)
- 创建对象
InjectionMetadata.forElements(elements, clazz);
- InjectionMetadata 对象的属性{ InjectionMetadata的injectedElements}就是记录了标注了 @Autowired、@Value 注解的Method和Field
- 存入缓存
- 返回 InjectionMetadata
检查 InjectionMetadata 对象
- 将 { InjectionMetadata的injectedElements} 记录到BeanDefinition中
- 将 { InjectionMetadata的injectedElements} 设置到 { InjectionMetadata的checkedElements} 表示已经检查过了
属性注入
- 拿到bean解析而成的InjectionMetadata
- 执行
CommonAnnotationBeanPostProcessor
处理@PostConstruct、@PreDestroy 标注的方法回调。处理@Resource 字段、方法的依赖注入
BeanPostProcessor执行过程:实例化前后置 -> 推断构造器后置 -> 实例化bean -> 合并BeanDefinition后置(hit) -> 实例化后后置 -> 属性注入后置(hit) -> 初始化前后置(hit) -> 初始化后后置 -> 销毁前后置(hit)
合并BeanDefinition阶段
回调父类方法
解析class生成 LifecycleMetadata
do...while 循环,递归父类,找到有 @PostConstruct、@PreDestroy 的方法 记录成 LifecycleElement,其中@PostConstruct记录在initMethods,@PreDestroy记录在destroyMethods
创建对象
new LifecycleMetadata(clazz, initMethods, destroyMethods)
记录有 @Resource 字段、方法的类,解析成
new InjectionMetadata(clazz, elements))
,其中elements的类型ResourceElement
解析class生成 InjectionMetadata
do...while 递归父类,找到有 @Resource 的字段、方法 装饰成 ResourceElement,记录在局部变量 elements
创建对象
InjectionMetadata.forElements(elements, clazz)
注:这里主要是缓存起来,一个类对应一个 LifecycleMetadata、InjectionMetadata 对象,对象的属性是记录 回调的字段、方法
属性注入阶段
- 拿到bean解析而成的InjectionMetadata
- 执行
初始化前阶段(父类)
- 从缓存中拿到类对应的 LifecycleMetadata,拿不到就解析类生成 LifecycleMetadata。
- 回调init方法
metadata.invokeInitMethods;
- 其实就是遍历 { InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata的initMethods} 属性,反射执行method。一个initMethod就是@PostConstruct标注的方法
销毁前阶段
- 从缓存中拿到类对应的 LifecycleMetadata,拿不到就解析类生成 LifecycleMetadata。
- 回调Destroy方法
metadata.invokeDestroyMethods;
- 其实就是遍历 { InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata的destroyMethods} 属性,反射执行method。一个destroyMethod就是@PreDestroy标注的方法
postProcessMergedBeanDefinition
AbstractAutowireCapableBeanFactory:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd,
@Nullable Object[] args) throws BeanCreationException {
// BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 从没有完成的 FactoryBean中移除
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
/**
* 推断构造器
* 创建bean实例化使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化。
* 该方法很复杂也很重要
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 从 beanWrapper中获取我们的早期对象
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
/**
* 后置处理器的【第四次】MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition
* 进行后置处理 @Autowired @Value的注解的预解析
*/
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex
);
}
mbd.postProcessed = true;
}
}
/**
* 该对象进行判断是否能够暴露早期对象的条件
* 单实例 this.allowCircularReferences 默认为true
* isSingletonCurrentlyInCreation(表示当前的bean对象正在创建singletonsCurrentlyInCreation包含当前正在创建的bean)
* 举例:
* class A { B b;}
* class B { A a;}
* 先实例化A --> singletonsCurrentlyInCreation = {A}
* 依赖注入B --> singletonsCurrentlyInCreation = {A,B}
* 依赖注入A --> singletonsCurrentlyInCreation = {A,B} ==> 发现 isSingletonCurrentlyInCreation(a) 满足条件,所以应该暴露A到三级缓存
*
* singletonsCurrentlyInCreation 是在单例bean 创建之前就设置的
* @see org.springframework.beans.factory.support.DefaultSingletonBeanRegistry的beforeSingletonCreation(java.lang.String)
* */
// 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");
}
/**
* 循环依赖-添加到三级缓存中
* 把我们的早期对象包装成一个 singletonFactory 对象,该对象提供了一个 getObject方法,该方法内部调用 getEarlyBeanReference(beanName, mbd, bean)
* 实现提前AOP
* */
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 填充bean,就是依赖注入或者给属性设置值
populateBean(beanName, mbd, instanceWrapper); // getBean()
// 进行对象初始化操作(在这里可能生成代理对象)
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
} else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
/**
* 这里是为了处理二级缓存中的bean 和 执行了初始化操作的 bean 不一致的校验,不一致说明可能存在
* 依赖注入的bean 和 实际存入单例池中的bean 不一致的问题。对于不一致,下面的处理是报错
*
*
* 比如 A 注入了 B,B 注入了 A
* 先是 getBean(A),然后其 populateBean 环节要注入B, 所以会 getBean(B),然后其 populateBean 环节要注入A,所以要 getBean(A)
* 此时发现A正在创建,所以会读取三级缓存的value,然后执行提前AOP得到一个 proxyBeanA ,并将 proxyBeanA 存入二级缓存,然后将 proxyBeanA 注入到 B中,
* 然后B就创建完了,然后B就会被注入到A中,所以A的 populateBean 结束了,然后会执行 initializeBean。假设在 initializeBean 生成了 proxyBeanA2 。
* 这就出现了 注入到B中的A,和实际最终生成的A不一致的问题,对于这中情况,只能直接报错了,下面的逻辑就是为了应付这种情况的,
*
* 注:当然 提前AOP 也不一定会创建代理对象,我这里只是举例了 提前AOP和初始化都创建了代理对象的场景,方便说明
*
* */
if (earlySingletonExposure) {
/**
* 去缓存中获取到我们的对象,由于传递的 allowEarlyReference 是false要求只能在一级二级缓存中去获取。
* 说白了,就尝试从二级缓存中获取bean。
*
* 注:在这里就能体会到三级缓存的好处了。因为这里是只会从一级缓存和二级缓存中获取内容(其实只可能从二级缓存中拿到,一级缓存是拿不到的,因为此时还未将单例bean存入一级缓存)
* 如果二级缓存拿到的值不为null,就校验一下 exposedObject(执行了初始化后置处理器返回的值) 和 bean(简单实例化出来的) 是否一致,
* 若不一致,就需要判断一下,这个bean是否注入给了其他bean对象,若注入给了其他bean对象,那么就只能报错了,因为已经注入给了其他bean的值 和 exposedObject 不一致。
*
* 假设我们采用二级缓存来解决循环依赖的问题。思路如下:
* 一级缓存用来缓存最终完全的bean,二级缓存一开始存入的是 ObjectFactory ,当出现了循环依赖时,读取二级缓存的值,然后回调方法 ObjectFactory的getObject 得到 提前AOP的bean。
* 将 提前AOP的bean 存入进二级缓存,也就是进行值覆盖。
*
* 一级缓存:< beanName,最终的bean >
* 二级缓存:< beanName, ObjectFactory 或者 提前AOP得到的bean >
*
* 这就会出现一个问题,很难确定二级缓存存储得值 是 ObjectFactory 还是 提前AOP得到的bean,
* 你可能会这么想 `earlySingletonReference instanceof ObjectFactory` 来检验,但这是不靠谱的,因为有可能bean的类型就是 ObjectFactory 的
* 所以呢,只能使用东西标记二级缓存的值 是 ObjectFactory 还是 提前AOP得到的bean,
* 比如 这么设计: ThreadLocal< beanName, boolean > earlyLocal : false 表示二级缓存的值是 ObjectFactory,true 表示二级缓存的值是 提前AOP得到的bean
*
* 那么下面的 判断逻辑应当改成 ` if ( earlySingletonReference != null && earlyLocal.get().get(beanName) )
*
* 所以呢肯定是需要使用东西来标记一下,是否执行了 ObjectFactory 得到 提前AOP得到的bean,Spring是采用的三级缓存来标记,
* 这就是为啥使用三级缓存
*
* */
Object earlySingletonReference = getSingleton(beanName, false);
/**
* 能够获取到,说明是在二级缓存拿到的。也就是这个 beanName 产生了循环依赖的问题,
* */
if (earlySingletonReference != null) {
/**
* 相等,说明初始化操作并没有对bean进行代理,那就没事。二级缓存的值作为最后要存入单例池中的值
* 不相等,说明对bean进行了代理。这就会导致循环依赖了bean的那些东西,注入的bean是不对的,我们需要判断一下
* 那些东西是否已经创建完了,创建完,那就没得搞了,只能报错了。
*/
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
/**
* hasDependentBean(beanName) 说明,这个bean已经注入到其他的bean对象中
* */
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
/**
* 获取依赖了 beanName 的bean。其实就是获取哪些bean注入了 beanName这个bean
*
* 在依赖注入时会记录,比如@Resource的注入逻辑 { org.springframework.context.annotation.CommonAnnotationBeanPostProcessor的autowireResource(BeanFactory, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.LookupElement, String)}
* */
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
/**
* 尝试挽救一下,如果 dependentBean 还没有创建完成,那就没问题了
*
* 创建完成的标记,是在这个地方设置的,也就是在 doGetBean 的一开始就设置了
* { AbstractBeanFactory的doGetBean(String, Clazz, Object[], boolean)}
* { AbstractBeanFactory的markBeanAsCreated(String)}
* */
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
/**
* 已经创建完了,就记录一下。
* */
actualDependentBeans.add(dependentBean);
}
}
// 报错
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(
actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."
);
}
}
}
}
// Register bean as disposable.
try {
/**
* 注册一次性bean 的销毁接口
* */
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
AutowiredAnnotationBeanPostProcessor:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Clazz<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
AutowiredAnnotationBeanPostProcessor:
private InjectionMetadata findAutowiringMetadata(String beanName, Clazz<?> 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);
/**
* metadata 是空 或者 metadata的属性{ InjectionMetadata的targetClass} != clazz
* 就需要刷新
* */
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
// 从 pvs 里面清空 metadata 的数据
metadata.clear(pvs);
}
/**
* 构建 InjectionMetadata 对象。
* 主要是解析clazz及其所有父类,拿到其中标注了 @Autowired、@Value 的 方法和字段
* 字段会包装成`new AutowiredFieldElement(field, required);`
* 方法会包装成`new AutowiredMethodElement(method, required, pd);`
* */
metadata = buildAutowiringMetadata(clazz);
// 存入缓存
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
AutowiredAnnotationBeanPostProcessor:
/**
* 解析clazz及其所有父类,拿到其中标注了 @Autowired、@Value 的 方法和字段构造成InjectionMetadata对象
* @param clazz
* @return
*/
private InjectionMetadata buildAutowiringMetadata(final AutowiredAnnotationBeanPostProcessor的buildAutowiringMetadata<?> clazz) {
/**
* 不是后候选的类,就返回空对象
*
* 只要clazz不是java包下的类,不是Ordered类 就是 候选类
* */
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
/**
* 先处理clazz,再循环 clazz 所有的父类
*
* 处理class里面所有的Field、Method
* */
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 遍历当前类声明的字段
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 找到 @Autowired、@Value、@javax.inject.Inject 其中一个,就返回,否则返回null
MergedAnnotation<?> 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;
}
/**
* 返回注解的 `required` 属性的值。如果没有就返回true(比如@Value)
* */
boolean required = determineRequiredStatus(ann);
// 构造成 `AutowiredFieldElement` 对象
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 遍历当前类声明的方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
// 不是桥接方法,桥接方法指的是jvm生成的方法。反正我们自己定义的方法不是
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
// 找到 @Autowired、@Value、@javax.inject.Inject 其中一个,就返回,否则返回null
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// 是静态的,不记录
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
// 方法没有参数,不记录
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
// 不是静态方法、方法参数列表个数大于0的才记录
// 返回注解的 `required` 属性的值。如果没有就返回true(比如@Value)
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 装饰成 AutowiredMethodElement 对象
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
// 存起来
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
CommonAnnotationBeanPostProcessor:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Clazz<?> beanType, String beanName) {
/**
* 找到有 @PostConstruct、@PreDestroy 的方法 记录成 LifecycleElement,然后属于 LifecycleMetadata
* */
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
/**
* 找到有 @Resource 的方法、字段的类 记录成 ResourceElement,然后属于 InjectionMetadata
* */
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
CommonAnnotationBeanPostProcessor:
private InjectionMetadata findResourceMetadata(String beanName, final 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);
}
/**
* 递归父类,将字段和方法上有 @Resource注解记录成 ResourceElement对象,所以是一个集合,
* 这个集合属于 InjectionMetadata 对象
* */
metadata = buildResourceMetadata(clazz);
// 缓存起来
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
CommonAnnotationBeanPostProcessor:
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
/**
* 就是有@Resource注解
* */
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
/**
* do...while 递归父类,找到有 @Resource 的字段、方法 装饰成 ResourceElement,记录在 elements
* 这个集合属于 InjectionMetadata 的,也就是说 InjectionMetadata 对应的就是一个类
* */
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
} else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
} else if (field.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
/**
* @Resouce 标注的方法,只允许有一个参数
* */
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
} else if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
} else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
postProcessProperties
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 若bw为nul1的话,则说明对象没有实例化
if (bw == null) {
if (mbd.hasPropertyValues()) {
// 进入if 说明对象有属性,bw为空,不能为他设置属性,那就在下面就执行抛出异常
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// Skip property population phase for null instance.
return;
}
}
/**
* 在属性被填充前,给 InstantiationAwareBeanPostProcessor 类型的后置处理器一个修改
* bean状态的机会。官方的解释是:让用户可以自定义属性注入。比如用户实现一
* 个 InstantiationAwareBeanPostProcessor 类型的后置处理器,并通过
* postProcessAfterInstantiation 方法向bean的成员变量注入自定义的信息
* 当时我们发现系统中的的 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 没有进行任何处理
* 若我们自己实现了这个接口可以自定义处理.... spring留给我们自已扩展接口的
* 特殊需求,直接使用配置中的信息注入即可
* */
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
/**
* 后置处理器的【第五次】InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation
* @see cn.haitaoss.javaconfig.beanpostprocessor.MyInstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(Object, String)
*
* 若存在后置处理器给我们属性赋值了,那么返回fale可以来修改我们的开关变量,就不会走下面的逻辑了
* */
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
/**
* 返回值为是否继续填充bean
* postProcessAfterInstantiation:如果应该在bean上面设置属性则返回true,否则返回 false
* 一般情况下,应该是返回true。
* 返回 false的话,将会阻止在此Bean实例上调用任何后续的 InstantiationAwareBeanPostProcessor
*/
return;
}
}
}
// 获取bean定义的属性
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
/**
* 判断我们的bean的属性注入模型
* AUTOWIRE_BY_NAME 根据名称注入
* AUTOWIRE_BY_TYPE 根据类型注入
*
* 可以这样子指定:@Bean(autowire = Autowire.BY_NAME)
* */
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// 把 PropertyValues 封装成为 MutablePropertyValues
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据bean的属性名称注入
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
/**
* 这里主要是会判断 有没有 { BeanWrapper的getPropertyDescriptor(String)} 是要给 { AbstractAutowireCapableBeanFactory的ignoredDependencyInterfaces}
* 的接口方法设置值的,排除掉这些 PropertyDescriptor。
* */
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据bean的类型进行注入
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
/**
* 这里主要是会判断 有没有 { BeanWrapper的getPropertyDescriptor(String)} 是要给 { AbstractAutowireCapableBeanFactory的ignoredDependencyInterfaces}
* 的接口方法设置值的,排除掉这些 PropertyDescriptor。
* */
autowireByType(beanName, mbd, bw, newPvs);
}
// 把处理过的属性覆盖原来的
pvs = newPvs;
}
/**
* 这里又是一种后置处理,用于在 Spring 填充属性到bean对象前,对属性的值进行相应的处理
* 比如可以修改某些属性的值。这时注入到bean中的值就不是配置文件中的内容了,
* 而是经过后置处理器修改后的内容
* */
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 判断是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
// 退出当前正在创建的 beanWrapper依赖的对象
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
/**
* 后置处理器的【第六次】InstantiationAwareBeanPostProcessor的postProcessProperties
* 进行字段和方法的依赖注入{ cn.haitaoss.javaconfig.beanpostprocessor.MyInstantiationAwareBeanPostProcessor的postProcessProperties(PropertyValues, Object, String)}
*/
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
/**
* 后置处理器的【第七次】cn.haitaoss.javaconfig.beanpostprocessor.MyInstantiationAwareBeanPostProcessor的postProcessPropertyValues(org.springframework.beans.PropertyValues, java.beans.PropertyDescriptor[], java.lang.Object, java.lang.String)
* 过时方法了,不建议使用
* @see cn.haitaoss.javaconfig.beanpostprocessor.MyInstantiationAwareBeanPostProcessor的postProcessPropertyValues(PropertyValues, Object, String)
*/
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
// 需要检查依赖
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
/**
* 其实,上面只是完成了所有注入属性的获取,将获取的属性封装在 PropertyValues的实例对象pvs中,
* 并没有应用到已经实例化的bean中。而
* @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory的applyPropertyValues(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.BeanWrapper, org.springframework.beans.PropertyValues)
* 则是完成这一步骤的
* */
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
AutowiredAnnotationBeanPostProcessor:
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
/**
* 拿到要注入member信息,有缓存机制。
* 在 { AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition} 就解析过了。
* */
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
/**
* 会根据 InjectionMetadata 需要注入的信息,
* 往 PropertyValues 中设置
* */
metadata.inject(bean, beanName, pvs);
} catch (BeanCreationException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
CommonAnnotationBeanPostProcessor:
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
/**
* 找到类里面有 @Resource 的字段、方法 包装成 ResourceElement 对象,然后属于 InjectionMetadata。
* */
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
/**
* 就是遍历 { InjectionMetadata的injectedElements} 进行注入
* */
metadata.inject(bean, beanName, pvs);
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}
InjectionMetadata.inject
/**
* 就是遍历其 injectedElements 属性,执行 { InjectedElement的inject(Object, String, PropertyValues)}
* @param target
* @param beanName
* @param pvs
* @throws Throwable
*/
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
/**
* 遍历 elementsToIterate。
*
* 比如 AutowiredAnnotationBeanPostProcessor 生成的 InjectionMetadata,其中的
* injectedElements 属性的值,其实就是 标注了@Autowired、@Value注解的字段和方法
* */
for (InjectedElement element : elementsToIterate) {
/**
* target 是 bean对象
* Field 的注入 { AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement的inject(Object, String, PropertyValues)}
* Method 的注入 { AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement的inject(Object, String, PropertyValues)}
*
* 如果是 ResourceElement 执行的是 { InjectedElement的inject(Object, String, PropertyValues)}
* */
element.inject(target, beanName, pvs);
}
}
}
InjectedElement的inject
/**
* 依赖注入:@Resource标注的字段、方法是执行父类方法 { InjectionMetadata.InjectedElement的inject(Object, String, PropertyValues)}
*
* 是字段,直接反射设置值
* `field.set(target, getResourceToInject(target, requestingBeanName));`
*
* 是方法,先判断是否应该跳过,不跳过就反射执行方法
* - 检查是否跳过 { InjectionMetadata.InjectedElement的checkPropertySkipping(PropertyValues)}
* 就是判断 PropertyValues 中有没有这个方法的信息,存在就跳过
* - 反射执行方法 `method.invoke(target, getResourceToInject(target, requestingBeanName));`
*
* 获取注入的值,会在这里判断是否创建代理对象 { CommonAnnotationBeanPostProcessor.ResourceElement的getResourceToInject(Object, String)}
* - element没有@Lazy注解,直接获取注入值 { CommonAnnotationBeanPostProcessor的getResource(CommonAnnotationBeanPostProcessor.LookupElement, String)}
* - element有@Lazy注解,构建代理对象作为注入值 { CommonAnnotationBeanPostProcessor的buildLazyResourceProxy(CommonAnnotationBeanPostProcessor.LookupElement, String)}
* 1. 定义内部类TargetSource
* TargetSource ts = new TargetSource() {
* @Override
* public Object getTarget() {
* // 执行代理对象的方法时,会调`getTarget`得到被代理对象,所以是在执行代理对象的方法时才会执行依赖的解析
* // 这就是@Lazy的原理哦,延时创建
* return getResource(element, requestingBeanName);
* }
* };
*
* 2. return 创建的代理对象
* ProxyFactory pf = new ProxyFactory();
* pf.setTargetSource(ts);
* return pf.getProxy(classLoader);
* getResource
* { CommonAnnotationBeanPostProcessor的getResource(CommonAnnotationBeanPostProcessor.LookupElement, String)}
* { CommonAnnotationBeanPostProcessor的autowireResource(BeanFactory, CommonAnnotationBeanPostProcessor.LookupElement, String)}
* - BeanFactory中没有依赖的名字`!factory.containsBean(name)`
* 构造 { CommonAnnotationBeanPostProcessor.LookupElement的getDependencyDescriptor()}
* 字段使用这个`new LookupDependencyDescriptor((Field) this.member, this.lookupType);`
* 方法使用这个`new LookupDependencyDescriptor((Method) this.member, this.lookupType);`
* 通过 DependencyDescriptor 从BeanFactory得到依赖值 { DefaultListableBeanFactory的resolveDependency(DependencyDescriptor, String, Set, TypeConverter)}
* - BeanFactory中有依赖的名字
* 通过name从BeanFactory得到依赖值 { AbstractBeanFactory的getBean(String, Clazz)}
* - 记录依赖关系 { ConfigurableBeanFactory的registerDependentBean(String, String)}
* Tips:所以说@Resource 是byName再byType
* */
AutowiredFieldElement的inject
/**
* 依赖注入:@Autowired、@Value 标注的字段会执行这个 { AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement的inject(Object, String, PropertyValues)}
* - 解析字段值 `value = resolveFieldValue(field, bean, beanName);`
* - 反射给字段设置值 `field.set(bean, value);`
*
* 解析字段值 { AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement的resolveFieldValue(Field, Object, String)}
* - 构造`new DependencyDescriptor(field, this.required);`
* - 通过 DependencyDescriptor 从BeanFactory得到依赖值 { DefaultListableBeanFactory的resolveDependency(DependencyDescriptor, String, Set, TypeConverter)}
* - 记录依赖关系 { ConfigurableBeanFactory的registerDependentBean(String, String)}
* - 缓存起来 `this.cachedFieldValue = cachedFieldValue;`
* */
AutowiredMethodElement的inject
/**
* 依赖注入:@Autowired、@Value 标注的方法会执行这个{ AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement的inject(Object, String, PropertyValues)}
* - 解析方法参数列表的值 `arguments = resolveMethodArguments(method, bean, beanName);`
* - 反射执行方法 `method.invoke(bean, arguments);`
*
* 解析参数列表的值 { AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement的resolveMethodArguments(Method, Object, String)}
* - 遍历方法参数列表,挨个解析 `for (int i = 0; i < arguments.length; i++) {}`
* - 构造,也就是一个参数是一个DependencyDescriptor
* MethodParameter methodParam = new MethodParameter(method, i);
* DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
* - 通过 DependencyDescriptor 从BeanFactory得到依赖值 { DefaultListableBeanFactory的resolveDependency(DependencyDescriptor, String, Set, TypeConverter)}
* - 记录依赖关系 { ConfigurableBeanFactory的registerDependentBean(String, String)}
* - 缓存起来 `this.cachedMethodArguments = cachedMethodArguments;`
* */
*
DefaultListableBeanFactory的resolveDependency
/**
* 解析依赖 { DefaultListableBeanFactory的resolveDependency(DependencyDescriptor, String, Set, TypeConverter)}
* 1. 有@Lazy就创建代理对象快速返回 `Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);`
* - 使用BeanFactory的AutowireCandidateResolver 解析 { ContextAnnotationAutowireCandidateResolver的getLazyResolutionProxyIfNecessary(DependencyDescriptor, String)}
* - 是否有@Lazy注解 { ContextAnnotationAutowireCandidateResolver的isLazy(DependencyDescriptor)}
* 字段 DependencyDescriptor:字段是否有@Lazy注解
* 方法的参数 DependencyDescriptor:参数是否有@Lazy注解,没有在接着看其Method是否有@Lazy注解
* - 有就创建代理对象 { ContextAnnotationAutowireCandidateResolver的buildLazyResolutionProxy(DependencyDescriptor, String)}
* TargetSource ts = new TargetSource() {
* public Object getTarget() {
* // 执行代理对象的方法时,会调`getTarget`得到被代理对象,所以是在执行代理对象的方法时才会执行依赖的解析
* // 这就是@Lazy的原理哦,延时解析依赖
* return dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
* }
* };
* ProxyFactory pf = new ProxyFactory();
* pf.setTargetSource(ts);
* return pf.getProxy();
*
* - 解析的值不是null,就return
*
* 2. 开始解析依赖 { DefaultListableBeanFactory的doResolveDependency(DependencyDescriptor, String, Set, TypeConverter)}
* */
DefaultListableBeanFactory的doResolveDependency
/**
* 开始解析依赖 { DefaultListableBeanFactory的doResolveDependency(DependencyDescriptor, String, Set, TypeConverter)}
*
* 标记一下,正在进行依赖解析 `InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);`
*
* 处理有@Value的情况,没有@Value就会往下判断了
* - 拿到@Value注解的值。查找顺序: 字段、方法参数没有@Value() -> 如果是方法参数依赖,就看看方法上有没有@Value
* `Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);`
* { QualifierAnnotationAutowireCandidateResolver的getSuggestedValue(DependencyDescriptor)}
*
* - value是String类型
* - 解析占位符 { AbstractBeanFactory的resolveEmbeddedValue(String)}
* `String strVal = resolveEmbeddedValue((String) value);`
* - 进行SpEL的解析,这里就会从容器中获取bean
* `value = evaluateBeanDefinitionString(strVal, bd);`
* { AbstractBeanFactory的evaluateBeanDefinitionString(String, BeanDefinition)}
*
* - 拿到 TypeConverter `TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());`
* SimpleTypeConverter typeConverter = new SimpleTypeConverter();
* typeConverter.setConversionService(getConversionService()); // 从容器中获取一个name 是 conversionService 的bean
* registerCustomEditors(typeConverter); // 使用BeanFactory的ResourceEditorRegistrar对typeConverter进行加工,默认是有这个`ResourceEditorRegistrar`
* return typeConverter;
* - 使用 TypeConverter,直接return 完成依赖的解析 `return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());`
*
* 依赖类型是多个的情况 `Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);` { DefaultListableBeanFactory的resolveMultipleBeans(DependencyDescriptor, String, Set, TypeConverter)}
* - 就是依赖的类型是 数组、Collection、Map的时候才会处理
* - 查找AutowireCandidates { DefaultListableBeanFactory的findAutowireCandidates(String, Clazz, DependencyDescriptor)}
* - 使用converter转换 `Object result = converter.convertIfNecessary(matchingBeans.values(), type);`
* - 使用依赖排序器,对结果进行排序 { DefaultListableBeanFactory的adaptDependencyComparator(Map)}
* - multipleBeans!=null 直接`return multipleBeans;`
*
* 查找AutowireCandidates `Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);` { DefaultListableBeanFactory的findAutowireCandidates(String, Clazz, DependencyDescriptor)}
* - 没有匹配的bean,这个依赖还是必须的,那就直接抛出异常 `matchingBeans.isEmpty() && isRequired(descriptor) `
*
* 存在多个候选bean,需要确定唯一一个。因为到这一步的依赖肯定是单个对象的,所以要从多个候选者中确定唯一的一个 `matchingBeans.size() > 1`
* - { DefaultListableBeanFactory的determineAutowireCandidate(Map, DependencyDescriptor)}
*
* 拿到唯一的bean `instanceCandidate = matchingBeans.get(autowiredBeanName);`
*
* 是否需要实例化,
* if (instanceCandidate instanceof Class)
* instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); // 这个就是 `getBean()`
*
* 返回依赖的值 `return instanceCandidate;`
*
* 移除标记 `ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);`
*
* Tips:先判断是不是@Value的自动注入,解析结果不为null直接return;再看看依赖类型是不是多个(数组、集合、Map) 解析到值就return;最后就是依赖类型是单个对象的情况咯,
* 单个对象的依赖就需要从多个候选者中确定唯一一个,确定不了就报错咯
* */
DefaultListableBeanFactory的findAutowireCandidates
/**
* { DefaultListableBeanFactory的findAutowireCandidates(String, Clazz, DependencyDescriptor)}
*
* - 局部变量,记录候选bean,key是beanName,value是bean对象或者是beanClass `Map<String, Object> result = CollectionUtils.newLinkedHashMap();`
*
* - 通过类型从BeanFactory找到匹配的candidateNames { BeanFactoryUtils的beanNamesForTypeIncludingAncestors(ListableBeanFactory, Clazz, boolean, boolean)}
* { DefaultListableBeanFactory的getBeanNamesForType(Clazz, boolean, boolean)}
* { DefaultListableBeanFactory的doGetBeanNamesForType(ResolvableType, boolean, boolean)}
* - 先从 BeanDefinitionMap 中找,根据依赖的类型进行匹配
* - 再从 manualSingletonNames 中找,根据依赖的类型进行匹配。这种是 { DefaultListableBeanFactory的registerSingleton(String, Object)} 这样子注册的,直接就放到单例池不会在BeanDefinitionMap中有记录
*
* - 再从 resolvableDependencies 找到类型匹配的候选者。因为依赖是已经实例化好了,所以直接记录到result中。
* `result.put(beanName, autowiringValue);`
* Tips:resolvableDependencies 也叫bean伪装,因为这些依赖值是直接new出来的,不是通过`getBean()` 创建出来的。相当于扩展了BeanFactory可以注入的依赖类型。
*
* - 遍历 candidateNames,是自动注入候选者就 `getBean()` 创建出bean对象,然后存到result中
* 是自动注入候选者 { QualifierAnnotationAutowireCandidateResolver的isAutowireCandidate(BeanDefinitionHolder, DependencyDescriptor)}
* 1. 先检查 这个就是检查BeanDefinition的属性值 { AbstractBeanDefinition的isAutowireCandidate()}
* 2. 匹配了,再检查字段依赖@Qualifier校验,和方法依赖其参数@Qualifier校验
* 3. 匹配了,是方法依赖且方法返回值不是Void,再才进行方法@Qualifier的匹配
* Tips:就是看看 @Qualifier("name") 与 candidateName 一致,就是true
*
* 是,就记录到result中 { DefaultListableBeanFactory的addCandidateEntry(Map, String, DependencyDescriptor, Clazz)}
* 分为三种情况:
* 1. 依赖类型是 数组、集合、Map等 `descriptor instanceof MultiElementDescriptor`
* 依赖类型是多个,所以需要把类型的bean都通过BeanFactory创建出来
* - 通过BeanFactory得到bean实例 { DependencyDescriptor的resolveCandidate(String, Clazz, BeanFactory)}
* - 记录 `result.put(candidateName, beanInstance);`
*
* 2. candidateName 已经在单例池创建好了,所以可以直接拿
* - 通过BeanFactory得到bean实例 { DependencyDescriptor的resolveCandidate(String, Clazz, BeanFactory)}
* - 记录 `result.put(candidateName, beanInstance);`
*
* 3. 依赖类型不是多个,且单例池没有,那么只记录其Clazz,目的是防止不依赖的bean也被创建了
* - 从BeanFactory中 通过beanName拿到其类型, { AbstractBeanFactory的getType(String)}
* - 记录 `result.put(candidateName, getType(candidateName));`
* Tips:确定好唯一一个beanName的时候才会在实例化的。
*
* Tips: `DependencyDescriptor的resolveCandidate` 其实就是 `beanFactory.getBean(beanName)`
*
* - 返回 result
* */
DefaultListableBeanFactory的determineAutowireCandidate
/**
* 确定自动注入候选者 { DefaultListableBeanFactory的determineAutowireCandidate(Map, DependencyDescriptor)}
*
* 先通过@Primary查找 { DefaultListableBeanFactory的determinePrimaryCandidate(Map, Clazz)}
* 如果 candidateName 有@Primary就返回。这里是会有判断的存在多个候选者有@Primary就抛出异常,所以说一个依赖类型只能有一个@Primary注解标注
* `return candidateName;`
*
* 没有找到@Primary,在通过beanClass的@Priority(1) { DefaultListableBeanFactory的determineHighestPriorityCandidate(Map, Clazz)}
* 返回排序值小的结果。这个是为了处理依赖类型是父类,然后容器中有多个子类实现的时候,可以通过@Priority(1) 来决定那个子类优先级搞。
* `return candidateName;`
* Tips:如果容器存在同一类型的bean有多个,就会报错,因为@Primary()的值都一样,无法确定,只能报错咯
*
* 兜底方法,bean实例是resolvableDependencies里面的 或者 beanName是(字段名 或者 方法参数名),也能确定出唯一的候选者
* `return candidateName;`
*
* 都没得,就``return null``
*
* Tips: 如果依赖类型不是多个的会通过 @Primary -> @Priority -> bean实例是resolvableDependencies里面的 -> beanName是(字段名 或者 方法参数名) 确定出唯一的候选者
* */
AbstractBeanFactory的evaluateBeanDefinitionString
/**
* 比如 @Value("的{beanA}")
*
* { AbstractBeanFactory的evaluateBeanDefinitionString(String, BeanDefinition)}
*
* 使用 `StandardBeanExpressionResolver` 进行计算 { StandardBeanExpressionResolver的evaluate(String, BeanExpressionContext)}
* `return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));`
*
* // value 就是 "的{beanA}" ,而beanExpressionParserContext 就是替换掉 的{}。也就是变成了 beanA ,也就是要访问 beanA这个属性
* Expression expr = new SpelExpressionParser().parseExpression(value, this.beanExpressionParserContext);
* StandardEvaluationContext sec = new StandardEvaluationContext(evalContext);
* // 设置属性访问器,就是用来解析 beanA 属性时,会调用这个访问器来获取值
* sec.addPropertyAccessor(new BeanExpressionContextAccessor());
* // 返回SpEL解析的结果
* expr.getValue(sec);
*
* 通过属性访问器,读取 beanA 属性值 { BeanExpressionContextAccessor的read(EvaluationContext, Object, String)}
* `(BeanExpressionContext) target).getObject(name)` { BeanExpressionContext的getObject(String)}
* 而 BeanExpressionContext 包装了BeanFactory和Scope。所以`getObject`
*
* if (this.beanFactory.containsBean(key)) {
* return this.beanFactory.getBean(key);
* }
* else if (this.scope != null) {
* return this.scope.resolveContextualObject(key);
* }
* else {
* return null;
* }
* */
TypeConverterSupport的convertIfNecessary
对依赖进行转换是执行`TypeConverterSupport的convertIfNecessary`。
`TypeConverterSupport` 其实是聚合了 `PropertyEditor` 和 `ConversionService`,这两个才是真正干活的东西。
`ConversionService`真正干活是使用`GenericConverter`,`ConversionService`只是聚合了多个`GenericConverter`而已。
`PropertyEditorRegistrar` 是用来加工 `PropertyEditorRegistry`的,就是用来给其设置`PropertyEditor`的。
扩展`PropertyEditorRegistrar` 是通过 `CustomEditorConfigurer`
`PropertyEditorSupport` 是JDK提供的,`ConversionService`是Spring提供的。
/**
* 依赖注入时,会拿到TypeConverter { AbstractBeanFactory的getTypeConverter()} ,进行转换
* SimpleTypeConverter typeConverter = new SimpleTypeConverter();
* // 从容器中获取一个name是 conversionService 的bean
* typeConverter.setConversionService(getConversionService());
* // 使用BeanFactory的ResourceEditorRegistrar对typeConverter进行加工
* // 主要是设置这个属性 { PropertyEditorRegistrySupport的overriddenDefaultEditors}
* registerCustomEditors(typeConverter);
*
* 执行转换 { TypeConverterSupport的convertIfNecessary(Object, Clazz, MethodParameter)}
*
* 拿到自定义的PropertyEditor `PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);`
* 先使用 propertyName + requiredType 从这个属性找 { PropertyEditorRegistrySupport的customEditorsForPath}
* 找不到在使用 requiredType 从这个属性找 { PropertyEditorRegistrySupport的customEditors}
* Tips: 可以通过往容器中注入 CustomEditorConfigurer 来扩展这两个属性值
*
* 没有自定义的 PropertyEditor 但是有 ConversionService
* 通过值类型 和 要赋值的对象 类型,判断是否可以转换。 { ConversionService的canConvert(TypeDescriptor, TypeDescriptor)}
* 其实就是遍历 ConversionService 的属性 { GenericConversionService.Converters} 找到合适的 GenericConverter
* { GenericConversionService.Converters的find(TypeDescriptor, TypeDescriptor)}
* { GenericConversionService.Converters的getRegisteredConverter(TypeDescriptor, TypeDescriptor, GenericConverter.ConvertiblePair)}
*
* 可以,就使用converter转换 { ConversionService的convert(Object, TypeDescriptor, TypeDescriptor)}
*
* return 装换的结果
*
* 执行转换 { TypeConverterDelegate的doConvertValue(Object, Object, Clazz, PropertyEditor)}
* 没有自定义的PropertyEditor 那就找默认的,先从这里面找 { PropertyEditorRegistrySupport的overriddenDefaultEditors}
* 找不到在重这里面找 { PropertyEditorRegistrySupport的defaultEditors}
*
* return 装换的结果
*
* Tips: 具体的转换功能是有 PropertyEditor 和 ConversionService 实现的,而 ConversionService 的具体转换功能是由 GenericConverter 实现的。
* */