Spring之依赖注入底层源码解析
- Spring依赖注入底层流程图
- Spring中依赖注入的方式
- 手动注入
- 自动注入
- @Autowired自动注入
- 寻找注入点
- static的字段或方法为什么不支持依赖注入
- 桥接方法
- 注入点进行注入
- 字段注入
- set方法注入
- 注入点注入流程图
Spring依赖注入底层流程图
- 首先先去找到所有注入点,注入点分为两种: 被@Autowired注解了的属性 以及 被@Autowired注解了的方法
- 遍历每个注入点
- 根据注入点去找Bean,这里如果注解了属性的会根据属性的类型去找Bean,如果注解了的是方法,那就根据方法中的参数类型去找Bean
- 对于找到有几个Bean
- 如果找到一个Bean,直接把这个Bean进行注入
- 如果找到多个Bean,会从多个Bean中确定出一个Bean
- 先判断是不是isAutowiredCandidate
- 再判断是不是复合Qualifier
- 如果还有多个,取@Primary的Bean
- 取出优先级最高的Bean
- 根据名字进行筛选,筛选出唯一的Bean
- 如果是根据属性注入的,那么就是根据属性名字去找
- 如果是根据set方法,那就是参数名字
- 如果没有找到Bean
- 如果@Autowired的reuqired属性为true,也就是说注入点必须被注入,那么就会报错
Spring中依赖注入的方式
对于Spring中依赖注入的方式,分为两种:
- 手动注入
- set方法注入
- 构造方法注入
- 自动注入
- XML的autowire自动注入
- @Autowired注解的自动注入
手动注入
在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定的值,下面这种底层是通过set方法进行注入
<bean name="userService" class="linc.fun.service.UserService">
<property name="orderService" ref="orderService"/>
</bean>
下面这种是通过构造方法进行注入
<bean name="userService" class="linc.fun.service.UserService">
<constructor‐arg index="0" ref="orderService"/>
</bean>
自动注入
自动注入又分为两种
- XML的autowire自动注入
- @Autowired注解的自动注入
XML的autowire自动注入
在XML中,我们可以在定义一个Bean时去指定这个Bean的自动注入模式:
- byType
- byName
- constructor
- default
- no
<bean id="userService" class="linc.fun.service.UserService" autowire="byType"/>
如果这么写,表示Spring会自动的给userService中所有的属性进行自动赋值,不需要在属性上加@Autowired注解,但需要这个属性有对应的set方法
PropertyDescriptor对象
在创建Bean的过程中,在填充属性时,Spring会去解析当前类,把当前类的所有方法都解析出来,Spring会解析每个方法得到对应的PropertyDescriptor对象,PropertyDescriptor有几个属性:
public class PropertyDescriptor extends FeatureDescriptor {
private Reference<? extends Class<?>> propertyTypeRef;
private final MethodRef readMethodRef = new MethodRef();
private final MethodRef writeMethodRef = new MethodRef();
private Reference<? extends Class<?>> propertyEditorClassRef;
private boolean bound;
private boolean constrained;
// The base name of the method name which will be prefixed with the
// read and write method. If name == "foo" then the baseName is "Foo"
private String baseName;
private String writeMethodName;
private String readMethodName;
public PropertyDescriptor(String propertyName, Class<?> beanClass)
throws IntrospectionException {
this(propertyName, beanClass,
Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName),
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));
}
.....
}
static final String GET_PREFIX = "get";
static final String SET_PREFIX = "set";
static final String IS_PREFIX = "is";
- name: 这个name并不是方法的名字,而是拿方法名字进行过处理后的名字
- 如果方法名字以"get"开头,比如"getXXX",那么name=XXX
- 如果方法名字以"is"开头,比如"isXXX",那么name=XXX
- 如果方法名字以"set"开头,比如"setXXX",那么name=XXX
- readMethodRef: 表示get方法的Method对象的引用
- readMethodName: 表示get方法的名字
- writeMethodRef: 表示set方法的Method对象的引用
- writeMethodName: 表示set方法的名字
- propertyTypeRef: 如果有get方法那么对应的就是返回值的类型,如果set方法那么对应的就是set方法中唯一参数的类型
get,set方法的定义
对于get方法的定义是: 方法参数个数为0,并且方法名字以"get"开头或者方法名字以"is"开头并且方法的返回类型为boolean
对于set方法的定义是: 方法参数个数为1,并且方法以"set"开头并且方法返回类型为void
byName自动填充属性时的流程
Spring在通过byName的自动填充属性时的流程是:
- 找到所有set方法所对应的XXX部分的名字
- 根据XXX部分的名字去获取Bean
byType的自动填充属性时的流程
- 获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取Bean
- 如果找到多个,会报错
constructor注入
以上,分析了autowire的byType和byName情况,那么接下来分析constructor,constructor表示通过构造方法注入,其实这种情况就比较简单了,没有byType和byName那么复杂
如果是constructor,那么就可以不写set方法了,当某个Bean是通过构造方法来注入时,Spring利用构造方法的参数信息从Spring容器中去找Bean,找到Bean之后作为参数传给构造方法,从而实例化得到一个Bean对象,并完成属性赋值(属性赋值的代码需要程序员来实现)
这里,我们只考虑只有一个有参数构造方法,其实构造方法注入相当于 byType+byName ,普通的byType是根据set方法的参数类型去找Bean,找到多个会报错,而constructor就是通过构造方法中的参数类型去找Bean,如果找到多个会根据参数名确定
为什么选择使用@Autowired,而不用XML的形式呢
@Autowired注解相当于XML中的autowire属性的注解方式的替代
官网如下解释: 从本质上将,@Autowired注解提供了与autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性
Essentially, the @Autowired annotation provides the same capabilities as described in Autowiring Collaborators but with more fine‐grained control and wider applicability
这里强调的是更细粒度的控制
XML中的autowire控制的是整个Bean的所有属性,而@Autowired注解是直接写在某个属性上、某个set方法、某个构造方法上的
倘若我们使用XML的形式,如果用XML中的autowire=constructor,在拥有多个构造方法的情况下,无法进行很好的控制,但是通过@Autowired注解可以直接指定想用哪个构造方法
同时,用@Autowired注解,还可以控制哪些属性想被自动注入,哪些属性不想,这也是细粒度的控制
但是@Autowird无法区分byType和byName,@Autowired是先byType,如果找到多个就会选择byName
那么XML的自动注入底层其实也就是
- set方法注入
- 构造方法注入
@Autowired注解的自动注入
@Autowired注解是byType+byName的结合
对于@Autowired注解可以有如下几种使用方式
- 属性上: 先根据属性类型去找Bean,如果找到多个再根据属性名去确定一个
- 构造方法: 现根据方法参数类型去找Bean,如果找到多个再根据参数名去确定一个
- set方法上: 先根据方法参数类型去找Bean,如果找到多个再根据参数名去确定一个
对于底层到了
- 属性注入
- set方法注入
- 构造方法注入
寻找注入点
在创建一个Bean的过程中,Spring会利用AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition找出注入点并且缓存
/**
* 实例化后的合并BeanDefinition之后的BeanDefinition进行处理
* 找注入点
*/
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
/**
* 寻找注入点,看哪些需要注入,哪些set方法上加了注解
*/
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;
}
找注入点的流程
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
// 如果一个Bean的类型是String...,那么则根本不需要进行依赖注入
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 遍历targetClass中的所有Field
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// field上是否存在@Autowired、@Value、@Inject中的其中一个
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
// static filed不是注入点,不会进行自动注入
// 在两个bean都是原型bean的情况下,其中一个是static bean注入,可能导致对象内部属性的值发生变化
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));
}
});
// 遍历targetClass中的所有Method
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 处理桥接方法 泛型的时候,字节码会有两个set方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
// method上是否存在@Autowired、@Value、@Inject中的其中一个
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// static method不是注入点,不会进行自动注入
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
// set方法最好有入参,没有就会打印一条日志
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
// 判断是否是required = true 如果是,但是没找到可以赋值给它就会报错,false就没事
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
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);
}
- 遍历当前类的所有的属性字段field
- 查看字段上是否存在@Autowired、@Value、@Inject中其中任意一个,存在则认为该字段是一个注入点
- 如果字段是static,则不进行注入
- 获取@Autowired中的required属性的值
- 将字段信息构建成一个AutowiredFieldElement对象,作为一个注入点对象添加到currElements集合中
- 遍历当前类的所有方法Method
- 判断当前Method是否存在桥接方法,如果是,找到原方法
- 查看方法上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该方法是一个注入点
- 如果方法是static的,则不进行注入
- 获取@Autowired中的required属性的值
- 将方法信息构造成一个AutowiredMethodElement对象,作为一个注入点对象添加到currElements集合中
- 遍历完当前类的字段和方法后,将遍历父类的,直到没有父类
- 最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合对象,并且缓存
static的字段或方法为什么不支持依赖注入
@Component
@Scope("prototype")
public class CService {
}
@Component
@Scope("prototype")
public class DService {
@Autowired
private static CService cService;
private void test() {
System.out.println("test...");
}
}
在CService和DService都是原型Bean的情况下,倘若Spring支持static字段进行自动注入,那么现在调用两次
@Test
public void testPrototypeStatic() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
DService d1 = ctx.getBean(DService.class);
DService d2 = ctx.getBean(DService.class);
}
对于此时,d1的CService值是什么?还是它自己注入的值吗
很显然不是,一旦d2创建好了,static Cservice字段的值就发生了改变了,从而会出现bug
桥接方法
// class version 52.0 (52)
// access flags 0x21
// signature Ljava/lang/Object;Llinc/cool/service/UserInterface<Llinc/cool/service/OrderService;>;
// declaration: linc/cool/service/UserService implements linc.cool.service.UserInterface<linc.cool.service.OrderService>
public class linc/cool/service/UserService implements linc/cool/service/UserInterface {
// compiled from: UserService.java
// access flags 0x2
private Llinc/cool/service/OrderService; orderService
// access flags 0x1
public <init>()V
L0
LINENUMBER 10 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Llinc/cool/service/UserService; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public test()V
L0
LINENUMBER 13 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 0
INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String;
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
LDC ".test()"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L1
LINENUMBER 14 L1
RETURN
L2
LOCALVARIABLE this Llinc/cool/service/UserService; L0 L2 0
MAXSTACK = 3
MAXLOCALS = 1
// access flags 0x1
public setOrderService(Llinc/cool/service/OrderService;)V
@Lorg/springframework/beans/factory/annotation/Autowired;()
L0
LINENUMBER 22 L0
ALOAD 0
ALOAD 1
PUTFIELD linc/cool/service/UserService.orderService : Llinc/cool/service/OrderService;
L1
LINENUMBER 24 L1
RETURN
L2
LOCALVARIABLE this Llinc/cool/service/UserService; L0 L2 0
LOCALVARIABLE orderService Llinc/cool/service/OrderService; L0 L2 1
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1041 桥接方法
public synthetic bridge setOrderService(Ljava/lang/Object;)V
@Lorg/springframework/beans/factory/annotation/Autowired;()
L0
LINENUMBER 10 L0
ALOAD 0
ALOAD 1
CHECKCAST linc/cool/service/OrderService
INVOKEVIRTUAL linc/cool/service/UserService.setOrderService (Llinc/cool/service/OrderService;)V
RETURN
L1
LOCALVARIABLE this Llinc/cool/service/UserService; L0 L1 0
MAXSTACK = 2
MAXLOCALS = 2
}
可以看到UserService的字节码中有两个setOrderService方法
public setOrderService(Llinc/cool/service/OrderService;)V
public synthetic bridge setOrderService(Ljava/lang/Object;)V
并且都是存在@Autowired注解的,所以在Spring中需要处理这种情况,当遍历到桥接方法时,得找到原方法
注入点进行注入
Spring在AutowiredAnnotationBeanPostProcessor#postProcessProperties方法中,会遍历所找到的注入点依次进行注入
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 找注入点(所有被@Autowired注解了的Field或Method) 此时已经可以直接从缓存中拿出来了
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 给字段赋值,给方法参数赋值
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;
}
/**
* 注入
*/
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()) {
// 遍历每个注入点进行依赖注入
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
字段注入
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
...
/**
* 字段的注入
*/
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 这里没有进行判断Pvs有没有,和method有点区别
Field field = (Field) this.member;
Object value;
if (this.cached) {
// 对于原型Bean,第一次创建的时候,也找注入点,然后进行注入,此时cached为false,注入完了之后cached为true
// 第二次创建的时候,先找注入点(此时会拿到缓存好的注入点),也就是AutowiredFieldElement对象,此时cache为true,也就进到此处了
// 注入点内并没有缓存被注入的具体Bean对象,而是beanName,这样就能保证注入到不同的原型Bean对象
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
} catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
} else {
// 根据filed从BeanFactory中查到的匹配的Bean对象
value = resolveFieldValue(field, bean, beanName);
}
// 反射给filed赋值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
// 注册一下beanName依赖了autowiredBeanNames,
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
// 构造一个ShortcutDependencyDescriptor作为缓存,保存了当前filed所匹配的autowiredBeanName,而不是对应的bean对象 (考虑原型bean)
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
- 遍历所有的AutowiredFieldElement对象
- 将对应的字段封装为DependencyDescriptor对象
- 调用BeanFactory#resolveDependency方法,传入DependencyDescriptor对象,进行依赖查找,找到当前字段所匹配的Bean对象
- 将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortCutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该对象时,就可以拿缓存的结果对象beanName去BeanFactory中去拿Bean对象了,不用再次去进行查找
- 利用反射将结果赋值给对象的字段
Set方法注入
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
...
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 如果pvs中已经有当前注入点的值了,则跳过注入 看属性描述器中对应属性的名字在不在pvs里,在就跳过
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
Object[] arguments;
// 找值的
// 第一次注入是没有缓存的
if (this.cached) {
try {
arguments = resolveCachedArguments(beanName);
} catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
arguments = resolveMethodArguments(method, bean, beanName);
}
} else {
arguments = resolveMethodArguments(method, bean, beanName);
}
if (arguments != null) {
try {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
} catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}
@Nullable
private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String b
// 方法参数个数
int argumentCount = method.getParameterCount();
// 保存参数对应的Bean对象
Object[] arguments = new Object[argumentCount];
// 有几个方法参数就有几个依赖描述器
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
// 遍历每个方法参数,找到匹配的bean对象
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
// this.required: 是不是一定要赋值
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.req
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBe
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoin
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descripto
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == argumentCount) {
Iterator<String> it = autowiredBeans.iterator();
Class<?>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[
cachedMethodArguments[i] = new ShortcutDependencyDescripto
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
} else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
return arguments;
}
- 遍历所有的AutowiredMethodElement对象
- 遍历将对应的方法的参数,将每个参数封装成MethodParameter对象
- 将MethodParameter对象封装成DependencyDescriptor对象
- 调用BeanFactory#resolveDependency方法,传入DependencyDescriptor对象,进行依赖查找,摘到当前方法参数所匹配的Bean对象
- 将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建对象时,就可以直接拿缓存的结果对象beanName去BeanFactory中去拿Bean对象了,不用再次去进行查找
- 利用反射将找到的所有结果对象传给当前方法,并且执行