Spring 属性填充
Spring 属性填充过程,核心就是实现,对 @Value
、@Autowired
、@Resource
等属性或者方法修饰注解的依赖进行注入或者说是对于依赖对象的查找和填充过程。
@Value
,@Autowired
的处理类是通过AutowiredAnnotationBeanPostProcessor
处理的。
@Resource
是通过CommonAnnotationBeanPostProcessor
处理
上述的两个类也是我们本文中所涉及到的核心类。
属性填充的入口方法 DefaultListableBeanFactory#populateBean
, 下面我们就从入口方法开始一步步的解析 Spring IOC
对 Bean 属性填充的过程。
populateBean 方法
下面是 populateBean
的流程
(1)InstantiationAwareBeanPostProcessor
处理器 postProcessAfterinstantiation
方法的行, 该方法执行后可以判断是否继续执行默认的属性填充处理。
(2) 根据注入类型(byName/byType),提取依赖的bean, 并且统一存入 PropertyValues
中
(3) 应用 InstantiationAwareBeanPostProcessor
处理器的 postProcessProperties
方法,在属性填充之间对属性的再次梳理,典型的就行 AutowiredAnnotationBeanPostProcessor
实现 @Autowried 注解的解析。
(4) 将 PropertyValues
中的属性填充到 BeanWrapper
中。
下面是源码中的处理过程
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { //... //在属性被填充前,给 InstantiationAwareBeanPostProcessor 类型的后置处理器一个修改 bean 状态的机会。 //定义该类型的后置处理器,可以通过实现 InstantiationAwareBeanPostProcessorAdapter 抽象类完成。 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } // 从Bean定义里面把准备好的值都拿出来~~~ // 它是个MutablePropertyValues,持有N多个属性的值~~~ PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 自动注入模式 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { // by_name 是根据属性名称查找 bean // by_type 是根据属性类型查找 bean // 查找到 bean 之后进行 set 注入 MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; // 总结: // spring 自动注入通过某个类的 set 方法来查找 bean, byName 就是根据某个 set 方法所对应的属性名去查找 bean // byType 就是根据某个 set 方法的参数去找 bean // 如果目前采用注解的方式,很少使用到 } // 执行完成 Spring 的自动注入之后,就开始解析 @Autowired . 这里叫做实例化回调 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); // @Autowired 注解的 AutowiredAnnotationBeanPostProcessor // @Resource 注解的 CommonAnnotationBeanPostProcessor PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 调用 BeanPostProcessor 分别解析 @Autowired、@Resource、@Value 为属性注入值 // 此处会从后置处理,从里面把依赖的属性,值都拿到。AutowiredAnnotationBeanPostProcessor就是在此处拿出值的~~~ PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds =filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.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); } if (pvs != null) { // 完成 pvs 赋值的运用 applyPropertyValues(beanName, mbd, bw, pvs); } }
autowireByName
通过方法 beanName 来实现自动注入,因为在 Spring IOC 中beanName是唯一的, 所以这样的效率是最高的,复杂度最低,代码如下。
protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { //获取非简单类型属性的名称,且该属性未被配置在配置文件中 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { // 根据属性名称去查找 bean, 这个就是 byName Object bean = getBean(propertyName); // 给属性赋值 pvs.add(propertyName, bean); registerDependentBean(propertyName, beanName); //.... print log } else { //.... print log } } }
autowireByType
通过类型来获取 Bean 进行注入,由于在 Spring IOC 中,同一个类型的 Bean 可以存在多个,对比 autowireByName
处理要复杂一些。
protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<>(4); //查找到有对应 set 方法的属性 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. if (Object.class != pd.getPropertyType()) { // set 方法中的参数信息 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); // Do not allow eager init for type matching in case of a prioritized post-processor. // 当前 bean 是否实现了 PriorityOrdered boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); // 根据 bean 类型找 bean, 这里是 byType Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null) { pvs.add(propertyName, autowiredArgument); } for (String autowiredBeanName : autowiredBeanNames) { registerDependentBean(autowiredBeanName, beanName); if (logger.isTraceEnabled()) { logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'"); } } autowiredBeanNames.clear(); } } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); } } }
通过上面的代码我们可以看到在这里的它的核心方法也就是 resolveDependency
。
resolveDependency
再 resolveDependency 方法中首先判断了依赖的类型, 然后在做对应的处理, 核心的方法是 doResolveDependency
。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { // DependencyDescriptor 表示一个依赖,可以是一个属性字段,可能是一个构造方法参数,可能是一个 set 参数 // 根据 descriptor 去 BeanFactory 中找到 bean descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); // 如果是 Optional if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); } else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } else { // 在使用 @Autowired 注解时,也可以使用 @Lazy 注解,到时候注入的会是一个代理对象 Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { // 通过解析 descriptor 找到 bean 对象 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } }