概述
- 回顾
- addSingletonFactory方法
- populateBean方法
- 根据注入的类型进行提取依赖bean
- AUTOWIRE_BY_NAME
- unsatisfiedNonSimpleProperties
- PropertyDescriptor[] pds = bw.getPropertyDescriptors();
- PropertyValues pvs = mbd.getPropertyValues();
- AUTOWIRE_BY_TYPE
- resolveDependency
- getLazyResollutionProxyIfNecessary
- doResolveDependency
- 注入属性
- valueResolver.resolveValueIfNecessary(pv, originalValue);
- bw.setPropertyValues
- processLocalProperty
- ph.setValue
- initializeBean方法
- invokeAwareMethods方法
- invokeAwareMethods方法
- invokeCustomInitMethod方法
回顾
上一篇已经分析了如何去创建常规bean了,回归到我们的AbstractAutowireCapableBeanFactory中的doCreateBean方法,现在我们已经生成好了beanWrapper
//首先根据是否单例、是否允许循环依赖、该bean是否在创建中
//来判断是否需要进行曝光
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");
}
//将beanName与它的ObjectFactory放进SingleFactory里面去,也就是缓存中去
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
addSingletonFactory方法
源码如下
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
//上锁
synchronized (this.singletonObjects) {
//判断以及缓存中是否以及存在
//如果不存在
if (!this.singletonObjects.containsKey(beanName)) {
//如果一级缓存中没有,往三级缓存中添加beanName与它的beanFacytory
this.singletonFactories.put(beanName, singletonFactory);
//移除二级缓存的beanName
this.earlySingletonObjects.remove(beanName);
//已注册的单例中存放该beanName
this.registeredSingletons.add(beanName);
}
}
}
可以看到,这个方法的作用就是去进此时生成的单例bean添加进三级缓存中进行曝光,并且标识该bean已经注册了
这里之所以进行提前曝光,是因为bean还没创建好,前面只是通过构造函数来生成了beanWrapper,对于依赖bean是还没有进行创建的,所以这里的bean其实还没有创建好(缺少依赖bean的创建),所以要进行提前曝光,给依赖bean可以检测出是否发生了循环依赖
populateBean方法
此时我们已经将beanWrapper进行曝光了,接下来就要进行populateBean方法来进行属性注入
源码如下
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//如果beanWrapper为null
//代表此时的实例为null,那就不能进行属性注入了
if (bw == null) {
//判断RootBeanDefinition里面是否有原型的值等待注入
//如果有,抛错,因为不能注入
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
//如果没有,直接return返回
return;
}
}
// 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.
// 在InstantiationAwareBeanPostProcessors给多最后一次机会去改变beanwrapper
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
//开始进行属性注入
//获取要注入的属性
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//获取RootBeanDefinition注入的模式
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
//可以看到我们熟悉的byName和byType了
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
//根据byName进行属性注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
//根据byType进行属性注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
//将提取的依赖bean存入newPvs中
pvs = newPvs;
}
//判断后继处理器是否已经初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//判断是否需要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
//如果后继处理器已经初始化完成
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
//
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//对所有需要依赖检查的属性进行后处理,但此时还没有依赖检查
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
//如果需要类型检查
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//依赖检查,对应depends-on属性,3.0已经弃用这个属性了
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
//将属性应用到bean中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
总结一下populateBan方法的作用
- 调用InstantiationAwareBeanPostPostProcessor处理器的postProcessAfterInstantiation函数
- 根据注入的类型,byType或者byName来提取依赖的bean,并且统一存入PropertyValues中去
- 应用InstantiatinAwareBeanPostProcessor处理的postProcessPropertyValues的方法,对注入的属性再次处理
- 将找到的属性填充至BeanWrapper中,也就是PropertyValues中去
这里比较重点的就是第二和第四步的注入,其他感觉太难了,看不下去。。。
根据注入的类型进行提取依赖bean
注入的类型有两种
- byType
- byName
我们可以给bean去设置注入的类型
<bean id = "" class = "" autowire="byType|byName|constructor|default"/>
这里的自动注入是对依赖的bean进行自动注入,而不是本身。。。
对应的代码为如下
AUTOWIRE_BY_NAME
这是根据名字进行自动注入的方法,也就是依赖的name属性
源码如下
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取需要注入的依赖属性,注意这里是获取不是简单类型的,也就是基本数据类型
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
//遍历这些依赖属性
for (String propertyName : propertyNames) {
//判断Spring的IOC容器中是不是存在这个bean
//可以看出这就是ByName形式
if (containsBean(propertyName)) {
//调用getBean方法进行创建
//看到这就懂了,单例的时候是怎么递归创建依赖的
//并且怎么去检测循环依赖的
Object bean = getBean(propertyName);
//将生成的bean添加新PropertyValues中
pvs.add(propertyName, bean);
//进行注册该bean
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
步骤大概如下
- 获取需要依赖的属性
- 遍历需要依赖的属性
- 根据依赖的属性的beanName查看IOC容器里面是否有该bean,体现出了ByName
- 如果不存在该bean,抛错,表示没有找到匹配的bean
- 如果存在该bean,调用getBean方法去创建依赖的bean(又走那一套流程,所以说到底创建bean就是一个递归过程)
- 将创建好的bean放入PropertyValues中
- 对该bean进行注册
整体逻辑没什么,下面来看是如何获取依赖的属性的
unsatisfiedNonSimpleProperties
对应获取依赖的属性具体方法在这里,这个方法会主动排除简单属性,即引用类型和基本数据类型
源码如下
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
//创建一个treeSet进行去重
Set<String> result = new TreeSet<>();
//获取所有的依赖
PropertyValues pvs = mbd.getPropertyValues();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
//
for (PropertyDescriptor pd : pds) {
//只有写了set方法
//不在不检查依赖的集合中
//不是简单类型
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
//满足条件之后添加进里面
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
看代码比较抽象,所以决定举个栗子
配置文件只是简单的一个注入类型
类也很简单,只是简单地提供了一个set方法注入
下面我们直接看那两个集合是什么
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
结果如下
里面有两个对象
一个是bean自己的class,没有writeMethod
另外一个,关于twoPojo的,而且里面存称了writeMethod正式set方法!!!!
所以可以推测这个集合获取的是需要依赖的属性详情
PropertyValues pvs = mbd.getPropertyValues();
里面的东西如下所示
可以看到,里面完全就是配置文件里面的信息。。。。
所以,这个集合里面存储的是配置文件里面的依赖属性的信息
那么现在,这个for循环来剔除什么,就很容易看出了
回归到我们的for循环
for (PropertyDescriptor pd : pds) {
//只有写了set方法
//不在不检查依赖的集合中
//不是简单类型
//并且配置文件里面没有这个beanName,
//如果配置文件里有那就去IOC容器里面拿就好了,不需要自动注入
//而不是采用注入的方式
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
//满足条件之后添加进里面
result.add(pd.getName());
}
}
可以看到结果,result为0
假如我们去掉配置文件的property
可以看到结果带上了twoPOJO
下面再来看一下BeanUtils过滤了什么东西出来
可以看到其过滤一些类型
-
void类型
-
isPrimitiveOrWrapper:判断是不是包装类,也就是过滤包装类
-
Enum类型
-
Date类型
-
URI类型
-
URL类型
-
Locale类型
-
Class类型
-
CharSequence类型
总结一下哪种依赖bean会被
- 没有写Set方法的依赖会被过滤
- 位于不进行检查的集合中依赖会被过滤
- 配置文件中已经指定注入的类型会被过滤
- 属于简单类型的也会被过滤
AUTOWIRE_BY_TYPE
还有一种自动注入类型就是根据类型去寻找
对应的代码如下
对应的方法是autowireByType
源码如下
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取类型处理器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//使用一个LinkedHashSet来存储需要自动注入的bean的beanName
//之前存储beanName也是使用一个set进行去重,然后转化成一个字符串数组
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//可以看到这里同样要进行过滤,就不赘述了
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
//遍历需要注入的依赖
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
//判断该依赖是不是Object类型,(注意:过滤并没有将Object类型过滤)
if (Object.class != pd.getPropertyType()) {
//获取该bean的set方法的参数。。
//相当于就是获取类型了。。体现出了ByType
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//解析指定beanName的属性所匹配的至,并把解析到的属性名称存储在autowiredBeanNames中
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
//遍历需要注入的bean
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);
}
}
}
从这里可以看到两个细节
- Spring对于Object类型的,使用ByType是不会进行注入的
- 获取类型是通过过去Set方法的参数来实现的,参数其实就是Type了,可以看出是ByType的体现
- 通过resolveDependency来进行创建依赖
resolveDependency
可以看到,对ByType的依赖进行创建是交由DefaultListableBeanFactory来实现的,而ByName的依赖进行创建交由AbstractAutowireCapableFactory来实现的
源码如下
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
//扩展了对Optional类的支持
if (Optional.class == descriptor.getDependencyType()) {
//Optional类单独使用方法创建
return createOptionalDependency(descriptor, requestingBeanName);
}
//对于ObjectFactory和ObjectProvider也是单独方法创建
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
//对JavaInjectProviderClass进行单独处理
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
//对于其他一般类型
//使用AutowireCandidateResolver来进行注入
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//如果AutpwireCandidateResolver注入失败,使用doResolveDependency进行注入
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
可以看到,对于一些特定类型单独处理之外,其他的类型都会走相同的步骤(大部分)
getLazyResollutionProxyIfNecessary
对于一般类型,首先会经过这个方法进行处理
从这个方法的注释来看,感觉像是对切入点进行添加代理的。。
不过其默认实现直接返回Null,那就先不看了。
doResolveDependency
接下来执行这个方法进行处理
源码如下,可以看到十分恐怖。。。
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//获取类对象,也就是前面通过set方法拿到的参数
Class<?> type = descriptor.getDependencyType();
//支持新增的@Value注解
//@Value注解是可以直接用在类上的,所以这里是根据类获取其注解
//然后去相应配置中进行注入
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
//判断是不是@Value注入了
//所以ByName不会被@Value注入????
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) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
//考虑这个属性是不是多个Bean的,也就是处理集合类型
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//查找出所有的候选者
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) {
//如果存在两个或两个意思,执行下面操作
//决定使用哪个候选者
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
//判断是否可以决定出来
if (autowiredBeanName == null) {
//
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
//如果只有一个候选值,进行下面处理
// We have exactly one match.
//去获取唯一的一个候选者
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
//使用候选者的属性
//beanName为key
//依赖的对象就是候选者的value
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
//添加进集合
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
//此时让result为得出来的候选者
Object result = instanceCandidate;
//再判断是不是NullBean类型
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);
}
}
好复杂,看的要吐了。。。。。。
总结一下大概的过程
-
通过前面解析set方法得到的参数来获取Class类型
-
通过这个Class类型去判断其有没有被@Value注解标识
- 如果有,走另一个逻辑
- 如果没有,代表还是需要去注入
- 判断是不是集合类型的,如果是集合类型的,又走集合类型的处理
- 如果不是集合类型的,去获取所有候选者
- 判断候选者的数量
- 如果候选者数量存在两个以上
- 判断决定使用哪个候选者,如果决定不出来又是另外一个方法
- 如果决定出来了,该候选者就是依赖Bean的实例了
- 如果候选者只有一个,直接使用该候选者
- 如果候选者数量存在两个以上
- 然后对产生出来的候选者做一些判空处理
-
返回结果
大概的思路就是这样。。。。下次再仔细研究,这太难了
到了这里之后,我们就已经完成了对所有注入属性的获取,但是获取了属性是以PropertyValue形式存在的,还没有应用到已经实例化的bean中
注入属性
回到populate方法中,现在所有的依赖就已经创建好了,等待注入bean里面了,对应的执行的方法为applyPropertyValues方法,同时也是populateBean最后的执行方法
源码如下
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
//如果依赖为空直接返回
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
//判断依赖是不是已经转化为对应的类型
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
//如果转化成对应的类型,直接装入BeanWrapper中
bw.setPropertyValues(mpvs);
//结束返回
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
//将依赖放进original中
original = Arrays.asList(pvs.getPropertyValues());
}
//
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//获取对应的解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
//使用一个ArrayList去存储依赖的深拷贝对象
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
//遍历所有依赖
for (PropertyValue pv : original) {
//判断依赖是不是已经转换过了
if (pv.isConverted()) {
//如果转换过了就直接添加进集合中去
deepCopy.add(pv);
}
else {
//获取依赖的名字,变量名
String propertyName = pv.getName();
//获取依赖的值,此时已经是一个对象了
Object originalValue = pv.getValue();
//如果值是AutowiredPropertyMarker..
//不太清楚这什么情况
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
//使用解析器进行解析
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
//将解析结果放在convertedValue变量中
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
//进行转化
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
//添加进深拷贝集合里面
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
//最后将所有深拷贝的依赖存进beanWrapper中
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
注入属性也好难懂,大体的过程是
- 判断依赖是不是都转化好了
- 如果都转化好了就直接添加进去beanWrapper中
- 如果没有转化好,就要进行对依赖深拷贝了
- 获取依赖的变量名和依赖的值,值通常是一个Spring自定义的RuntimeBeanReference
- 使用解析器进行转化
- 将转化后的值添加进去deepCopy集合中,deepCopy是一个ArrayList
- 最后将deepCopy集合存进beanWrapper中
所以,重点的部分在于解析和将解析后依赖存进beanWrapper这里,下面看看是如何进行解析的
valueResolver.resolveValueIfNecessary(pv, originalValue);
这个方法就是进行解析的
源码如下
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
//判断是不是RuntimeBeanReference
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
//判断是不是RuntimeBeanNameReference
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
//判断是不是BeanDefinitinHolder
else if (value instanceof BeanDefinitionHolder) {
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
//判断是不是BeanDefinition
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
BeanDefinition bd = (BeanDefinition) value;
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
ObjectUtils.getIdentityHexString(bd);
return resolveInnerBean(argName, innerBeanName, bd);
}
//判断是不是DependencyDescriptor
else if (value instanceof DependencyDescriptor) {
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
Object result = this.beanFactory.resolveDependency(
(DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter);
for (String autowiredBeanName : autowiredBeanNames) {
if (this.beanFactory.containsBean(autowiredBeanName)) {
this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);
}
}
return result;
}
//判断是不是ManagedArray
else if (value instanceof ManagedArray) {
// May need to resolve contained runtime references.
ManagedArray array = (ManagedArray) value;
Class<?> elementType = array.resolvedElementType;
if (elementType == null) {
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
else {
elementType = Object.class;
}
}
return resolveManagedArray(argName, (List<?>) value, elementType);
}
//判断是不是ManagedList
else if (value instanceof ManagedList) {
// May need to resolve contained runtime references.
return resolveManagedList(argName, (List<?>) value);
}
//判断是不是ManagedSet
else if (value instanceof ManagedSet) {
// May need to resolve contained runtime references.
return resolveManagedSet(argName, (Set<?>) value);
}
//判断是不是ManagedMap
else if (value instanceof ManagedMap) {
// May need to resolve contained runtime references.
return resolveManagedMap(argName, (Map<?, ?>) value);
}
//判断是不是ManagedProperties
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
Properties copy = new Properties();
original.forEach((propKey, propValue) -> {
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
if (propKey == null || propValue == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting Properties key/value pair for " + argName + ": resolved to null");
}
copy.put(propKey, propValue);
});
return copy;
}
//判断是不是TypeStringValue
else if (value instanceof TypedStringValue) {
// Convert value to target type here.
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
else {
return valueObject;
}
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting typed String value for " + argName, ex);
}
}
//判断是不是NullBean
else if (value instanceof NullBean) {
return null;
}
//如果都不是上述类型
else {
return evaluate(value);
}
}
可以看到,这里注入属性根据传进来的值是什么类型做了区分处理
- RuntimeBeanReference类型的
- RuntimeBeanNameReference类型的
- BeanDefinitionHolder类型的
- BeanDefiniton类型的
- DependencyDescriptor类型的
- ManagedArray类型的
- ManagedList类型的额
- ManagedSet类型的
- ManagedMap类型的
- ManagedProperty类型的
- NullBean类型的
- 其他类型,这里的其他类型已经就是对应的class类型了
一般传进来的是一个已经是对应的类型了
那就会直接对应最后的evaluate方法
源码如下
@Nullable
protected Object evaluate(@Nullable Object value) {
//对字符串进行处理
//主要的处理是将字符串解析为一个Bean对象
if (value instanceof String) {
return this.doEvaluate((String)value);
}
//对字符串数组进行处理
else if (value instanceof String[]) {
String[] values = (String[])((String[])value);
boolean actuallyResolved = false;
Object[] resolvedValues = new Object[values.length];
//其实就是遍历字符串数组,对每个字符串进行处理
for(int i = 0; i < values.length; ++i) {
String originalValue = values[i];
Object resolvedValue = this.doEvaluate(originalValue);
if (resolvedValue != originalValue) {
actuallyResolved = true;
}
resolvedValues[i] = resolvedValue;
}
return actuallyResolved ? resolvedValues : values;
}
//不是字符串也不是字符串数组,直接返回value,也就是创建好的对象
//一般直接在这里就返回了
else {
return value;
}
}
可以看到这个方法对字符串和字符串数组做了特殊处理,但这里是不可能出现String类型和字符串数组类型的。。。因为前面已经过滤掉了
bw.setPropertyValues
这个方法就是将依赖存进beanWrapper中了
可以看到,此时要注入的依赖都存进了deepCopy中
进来这个方法之后,可以看到这个方法是交由AbstractPropertyAccessor实现的,并且调用了重载方法
源码如下
@Override
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
throws BeansException {
//存储异常的
List<PropertyAccessException> propertyAccessExceptions = null;
//将传进来的依赖转为List
List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
//这个参数为false,不考虑下面这步
if (ignoreUnknown) {
this.suppressNotWritablePropertyException = true;
}
try {
//遍历传进来的所有依赖
for (PropertyValue pv : propertyValues) {
// setPropertyValue may throw any BeansException, which won't be caught
// here, if there is a critical failure such as no matching field.
// We can attempt to deal only with less serious exceptions.
try {
//进行注入
setPropertyValue(pv);
}
//下面都是捕捉异常处理,不看了
catch (NotWritablePropertyException ex) {
if (!ignoreUnknown) {
throw ex;
}
// Otherwise, just ignore it and continue...
}
catch (NullValueInNestedPathException ex) {
if (!ignoreInvalid) {
throw ex;
}
// Otherwise, just ignore it and continue...
}
//统计PropertyAccessException异常
catch (PropertyAccessException ex) {
if (propertyAccessExceptions == null) {
propertyAccessExceptions = new ArrayList<>();
}
propertyAccessExceptions.add(ex);
}
}
}
finally {
if (ignoreUnknown) {
this.suppressNotWritablePropertyException = false;
}
}
//这里是统计出现的PropertyAccessException
//最后全部抛出
// If we encountered individual exceptions, throw the composite exception.
if (propertyAccessExceptions != null) {
PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]);
throw new PropertyBatchUpdateException(paeArray);
}
}
可以看出这个方法是遍历所有的依赖,然后给每个依赖去执行setProperty方法,关键在于setProperty方法
点进来之后,你会发现IDEA会跳到这里来
但其实这个方法被AbstractNestablePropertyAccessor给重写了!!! 所以执行的不是这里的逻辑,这里是不会进来的(上当了)
所以我们应该从这里点击进去,才能继续断点调试
这个方法的源码如下
@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
//判断有没有token,一般的注入都不会进来这里
if (tokens == null) {
String propertyName = pv.getName();
AbstractNestablePropertyAccessor nestedPa;
try {
nestedPa = getPropertyAccessorForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
if (nestedPa == this) {
pv.getOriginalPropertyValue().resolvedTokens = tokens;
}
nestedPa.setPropertyValue(tokens, pv);
}
else {
//一般注入会进来这里
setPropertyValue(tokens, pv);
}
}
进来之后就是另外一个重载的方法
protected void setPropertyValue(AbstractNestablePropertyAccessor.PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
//这个tokens.key一般也是为0
if (tokens.keys != null) {
this.processKeyedProperty(tokens, pv);
} else {
//所以一般是进来这个方法
this.processLocalProperty(tokens, pv);
}
}
processLocalProperty
该方法的源码如下
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
//根据tokens的actualName获取注入依赖的信息
//比如之前的beanWrapper、一些Class信息
//可以理解成ph此时就是要被注入依赖的bean
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
if (ph == null || !ph.isWritable()) {
if (pv.isOptional()) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring optional value for property '" + tokens.actualName +
"' - property not found on bean class [" + getRootClass().getName() + "]");
}
return;
}
if (this.suppressNotWritablePropertyException) {
// Optimization for common ignoreUnknown=true scenario since the
// exception would be caught and swallowed higher up anyway...
return;
}
throw createNotWritablePropertyException(tokens.canonicalName);
}
Object oldValue = null;
try {
//获取依赖的value,此时是一个对象
Object originalValue = pv.getValue();
Object valueToApply = originalValue;
if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
if (pv.isConverted()) {
valueToApply = pv.getConvertedValue();
}
else {
if (isExtractOldValueForEditor() && ph.isReadable()) {
try {
oldValue = ph.getValue();
}
catch (Exception ex) {
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" +
this.nestedPath + tokens.canonicalName + "'", ex);
}
}
}
valueToApply = convertForProperty(
tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
//对bean进行注入依赖
ph.setValue(valueToApply);
}
catch (TypeMismatchException ex) {
throw ex;
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(
getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
if (ex.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());
}
else {
Throwable cause = ex.getTargetException();
if (cause instanceof UndeclaredThrowableException) {
// May happen e.g. with Groovy-generated methods
cause = cause.getCause();
}
throw new MethodInvocationException(propertyChangeEvent, cause);
}
}
catch (Exception ex) {
PropertyChangeEvent pce = new PropertyChangeEvent(
getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
ph.setValue
最后注入的步骤交由了BeanWrapperImpl来完成
源码如下
public void setValue(@Nullable Object value) throws Exception {
//获取Set方法的Method对象
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
//系统安全管理器
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(writeMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> writeMethod.invoke(getWrappedInstance(), value), acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
//使用反射工具让该set方法对象可访问
ReflectionUtils.makeAccessible(writeMethod);
//getWrappedInstance获取的就是要进行依赖注入的bean,value是要注入的依赖
//执行要进行依赖注入的bean的set方法完成依赖注入
writeMethod.invoke(getWrappedInstance(), value);
}
}
}
等执行完invoke方法之后,可以看到twoPojo成功注入了
所以,可以理解成注入属性的本质其实就是BeanWrapperImpl使用创建好的依赖和Set方法反射进行注入
现在也已经完成属性注入了
但此时仅仅只是将属性注入beanWrapper中,Bean基本上已经创建完,但整体的创建Bean流程还在AbstractAutowireCapableBeanFactory的doCreateBean方法,只有完成这个方法才算整个Bean创建完,现在还缺少一些生命周期的东西,比如init方法
下一步就是去执行initializeBean方法了
initializeBean方法
虽然方法名叫做initializeBean,但其实现在整个Bean大体上已经创建完了,之前在研究Bean的配置文件解析时,遇到过一个init-method属性,这个属性的作用就是在bean实例化后调用init-method指定的方法,来完成实例化前要做的动作,而这个属性起作用的为止在于初始化Bean的步骤里面
对应的源码如下
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
//获取系统的安全管理器,它的zuo'yong'shi
//当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),
//为了防止运行恶意代码对系统产生影响
//需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器。
//不过这里的关键还是执行invokeAwareMethods方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//执行invokeAwareMethods方法
invokeAwareMethods(beanName, bean);
}
//
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//应用后处理器的前初始化
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//执行init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//调用后处理器的后初始化
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这整体的流程清晰明了
- 执行invokeAwareMethods方法
- 调用后处理器的处理初始化前的逻辑
- 执行invokeInitMethods方法
- 调用后处理器的处理初始化后的逻辑
这里抛开后处理器的逻辑
invokeAwareMethods方法
使用过Spring的人都知道,bean对于IOC容器是没有意识的,不能获取IOC容器的服务,那么如果要想bean获取IOC的服务,那么就要让bean意识到IOC容器的存在,所以,对应的会有一系列Aware的接口,对应不同的IOC服务,只要bean实现了这个接口就可以获取对应的IOC服务,就不细说Aware接口
源码如下
private void invokeAwareMethods(String beanName, Object bean) {
//判断是不是Aware接口
if (bean instanceof Aware) {
//判断是不是里面的BeanNameAware接口
//该接口可以让bean获取自己在IOC容器里面的名字
if (bean instanceof BeanNameAware) {
//给bean注入自己的BeanName
((BeanNameAware) bean).setBeanName(beanName);
}
//判断是不是BeanClassLoaderAware接口
//该接口可以让bean获取IOC的类加载器服务
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
//给Bean注入BeanClassLoader
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
//判断是不是BeanFactoryAware接口
//该接口可以获取IOC的BeanFactory服务
if (bean instanceof BeanFactoryAware) {
//这一步的什么AbstractAutowireCapableBeanFactory.this,可以当成是一个this指针
//给Bean注入创建自己的Factory
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
可以看到,这个方法只是很简单地将所有Aware接口枚举出来,让后对应强转成接口类型后注入对应服务,从这里可以看到对应的Aware接口其实就三种
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
做好这些对Bean唤醒IOC服务了之后,接下来就是激活method-init方法了
invokeAwareMethods方法
该方法就是用来激活method-init方法的
源码如下
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//判断是不是InitializingBean类型
//这是要bean去实现InitializingBean接口才会去做的
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
//如果是,则需要调用afterPropertiesSet方法
//这里同样先不管系统的安全处理器,只知道这里会调用afterPropertiesSet方法
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//调用afterPropertySet方法
//并且可以看到是由bean本身自己调用的
((InitializingBean) bean).afterPropertiesSet();
}
}
//判断是不是NullBean.Class
if (mbd != null && bean.getClass() != NullBean.class) {
//获取method-init指定的方法名字
String initMethodName = mbd.getInitMethodName();
//并且这里还过滤了afterPropertiesSet方法
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
//执行方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
又看到了Spring遗留的一个知识,InitializingBean接口
- 判断Bean是不是实现了InitializingBean接口
- 如果实现了,有限执行接口中的afterPropertiesSet方法
- 去RootBeanDefinitin中寻找method-init属性
- 找到对应的方法,并且过滤掉afterPropertiesSet方法,当然这个过滤的前提是该Bean实现了InitializingBean接口
- 调用invokeCustomInitMethod方法实现
invokeCustomInitMethod方法
源码如下
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
throws Throwable {
//获取method-init属性
String initMethodName = mbd.getInitMethodName();
//断言
Assert.state(initMethodName != null, "No init method set");
//使用反射去获取该方法的Method对象
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
//如果获取到的Method对象为空
if (initMethod == null) {
//判断RootBeanDefinition中有没有设定强制执行
if (mbd.isEnforceInitMethod()) {
//如果为空又要强制执行就会报错
throw new BeanDefinitionValidationException("Could not find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
}
else {
//如果不强制执行,忽略,直接返回
if (logger.isTraceEnabled()) {
logger.trace("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
//如果不为空会做下面的处理
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
//不太搞懂这个方法,注释上说尽量获取接口方法
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
//安全管理器,先不做考虑研究
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(methodToInvoke);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> methodToInvoke.invoke(bean), getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
}
else {
try {
//通过反射工具让该方法可以被调用
ReflectionUtils.makeAccessible(methodToInvoke);
//通过反射执行这个方法
methodToInvoke.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
这里的大概逻辑也很简单
- 判断method-init属性是不是为空
- 如果为空,断言会抛错
- 如果不为空,通过反射去获取该方法的Method对象
- 如果Method对象为空,判断配置文件有没有设置强制执行,如果强制执行会抛错
- 如果Method对象为空,并且配置文件没有设置强制执行,那就直接忽略
- 通过反射去执行该Method
至此对象已经完成了属性注入与初始化了
最后
以上就是高高唇膏为你收集整理的Spring(十四):继续创建单例Bean,提前曝光、属性注入与初始化Bean的全部内容,希望文章能够帮你解决Spring(十四):继续创建单例Bean,提前曝光、属性注入与初始化Bean所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复