Spring中到底有几种依赖注入的方式?
首先分两种:
- 手动注入
- 自动注入
手动注入
在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定了值。
<bean name="userService" class="com.luban.service.UserService">
<property name="orderService" ref="orderService"/>
</bean>
上面这种底层是通过set方法进行注入。
<bean name="userService" class="com.luban.service.UserService">
<constructor-arg index="0" ref="orderService"/>
</bean>
上面这种底层是通过构造方法进行注入。
所以手动注入的底层也就是分为两种:
- set方法注入
- 构造方法注入
自动注入
自动注入也分为两种:
- XML的autowire自动注入
- @Autowired注解的自动注入
接下来开始源码分析
入口 - 属性填充阶段
直接看Bean生命周期的属性填充阶段:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {...}
// 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()) {...}
//属性值,用来通过set方法注入的值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//1. autowire自动注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
//autowire根据Name自动注入(其实只是收集注入值到newPvs中)
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
//autowire根据Type自动注入(其实只是收集注入值到newPvs中)
autowireByType(beanName, mbd, bw, newPvs);
}
//核心,ByName或者ByType找到属性对应的值以后,就会放到pvs中
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
//2.@Autowired注解注入
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
//默认提供的实现里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法直接给对象中的属性赋值
// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
// AutowiredAnnotationBeanPostProcessor会处理@Autowired、@Value、 @Inject 注解
// CommonAnnotationBeanPostProcessor会处理@Resource注解
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
//获取筛选后的propertydescriptor,属性描述器集合(排除被忽略的依赖项类型 或 在被忽略的依赖项接口上 定义的属性)
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//过时了,在工厂将给定的属性值应用到给定的bean之前,对它们进行后处理。
//允许检查是否满足了所有依赖项,例如基于bean属性设置器上的“Required”注解。
// 默认实现RequiredAnnotationBeanPostProcessor中,支持给"setXXX"方法加上@Required注解
// 标记为“必需的”,简单来说,就是要求pvs属性值中一定要存在 给@Required标记的set方法注入的值
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
//依赖项检查,确保所有公开的属性都已设置
//依赖项检查可以是对象引用、“简单”属性(原语和String)或所有(两者都是)
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
//3.属性赋值(把pvs里的属性值给bean进行赋值!!!!!)
//autowire自动注入,其实只是收集注入的值,放到pvs中,最终赋值的动作还是在这里!!
//PropertyValues中的值优先级最高
// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired的
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
1. autowire自动注入
xml中可以通过autowire属性设置:
<bean id="user" class="com.yth.service.User" autowire="byName"/>
@Bean方式也行
@ComponentScan("com.yth")
public class AppConfig {
@Bean(autowire = Autowire.BY_TYPE)
public OrderService orderService() {
return new OrderService();
}
}
ByName
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByName
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//1.1 获取当前bean中能进行自动注入的属性名
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
//遍历每个属性名,并去获取Bean对象,并设置到pvs中
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
//直接根据beanName获取Bean
Object bean = getBean(propertyName);
//这里把propertyName对应的属性值保存到了MutablePropertyValues
//暂时只是记录了一下,还没有赋值
pvs.add(propertyName, bean);
//记录一下propertyName对应的Bean被beanName给依赖了
//(之前讲DependsOn注解也走过这个方法)
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {...}
}
else {...}
}
}
- 直接根据beanName获取Bean
- 只做了记录,还没有进行赋值的动作!!
ByType
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByType
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {...}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//1.1 获取当前bean中能进行自动注入的属性名
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 an unsatisfied, non-simple property.
// 如果需要注入的属性类型是Object类型没有意义(注入的时候发现类型是Object这咋注入)
if (Object.class != pd.getPropertyType()) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
// 在优先级后处理器的情况下,不允许为了类型匹配而立即初始化。
// 为什么不允许,因为我自己是PriorityOrdered,是优先级最高的,不能有比我创建得更早的
// PriorityOrdered:Ordered接口的扩展,表示优先级排序:priorityorordered对象总是应用在普通Ordered对象之前,而不管其顺序值如何。
// eager表示立即初始化,表示在根据类型查找Bean时,允不允许进行Bean的创建,如果当前Bean实现了PriorityOrdered则不允许
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
//依赖注入描述器
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 1.2 根据类型找到结果(@Autowired注解也是用的这个方法,非常重要和复杂)
// 这个方法下一节再讲,很复杂!!
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
//和ByName同理,只是记录
pvs.add(propertyName, autowiredArgument);
}
//因为有可能注入的时候是个List<XXXX>,所以这里autowiredBeanNames是个集合
for (String autowiredBeanName : autowiredBeanNames) {
//记录一下autowiredBeanName对应的Bean被beanName给依赖了
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {...}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {...}
}
}
同理,只做了记录,还没有进行赋值的动作!!
1.1 获取当前bean中能进行自动注入的属性名
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#unsatisfiedNonSimpleProperties
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues();
//获取当前对象中,所有符合javaBean定义的有get/set方法的属性的属性描述器
// 底层其实只会判断get/set方法,有get/set方法就会解析成一个属性描述器,但是要求get/set方法满足一定的条件
// 条件简单理解总结就是:
// get方法的定义是: 方法参数个数为0个,并且方法名字以"get"开头
// 或者 方法名字以"is"开头并 且方法的返回类型为boolean
// set方法的定义是:方法参数个数为1个,方法名字以"set"开头,且方法返回类型为 void
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
//什么样的属性能进行自动注入?
//1.该属性有对应的set方法 pd.getWriteMethod() != null
//2.该属性类型没有在ignoredDependencyTypes中
//3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
//4.getPropertyValues中不能包含该属性 !pvs.contains(pd.getName())
//5.属性类型不是简单类型,比如int、Integer、int[]
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
什么样的属性能进行自动注入?
- 该属性有对应的set方法 pd.getWriteMethod() != null
- 该属性类型没有在ignoredDependencyTypes中
- 如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
- getPropertyValues中不能包含该属性 !pvs.contains(pd.getName())
- 属性类型不是简单类型,比如int、Integer、int[]
[2,3]:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#isExcludedFromDependencyCheck
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
//AutowireUtils.isExcludedFromDependencyCheck:排除了CGLIB定义的属性
//ignoredDependencyTypes:依赖项检查和自动装配时要忽略的依赖项类型,是一个类对象集合:例如,字符串。默认是没有的。
//ignoredDependencyInterfaces:依赖项检查和自动装配时要忽略的依赖项接口,是一个类对象的集合。默认情况下,只有BeanFactory接口被忽略。
return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}
[4]:比如我们可以在Bean生命周期的 BeanDefinition后置处理阶段,给PropertyValues赋值,这样相同的属性名称,在当前流程中就会跳过该属性,肯定程序员自定义的优先级高喽。
[5]:判断是否是简单类型
org.springframework.beans.BeanUtils#isSimpleProperty
public static boolean isSimpleProperty(Class<?> type) {
Assert.notNull(type, "'type' must not be null");
return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
}
public static boolean isSimpleValueType(Class<?> type) {
//isPrimitiveOrWrapper方法中,void/Void也会返回true,所以这里一开始就单独判断了一下。
return (Void.class != type && void.class != type &&
//以下这些都属于简单类型
//isPrimitiveOrWrapper:检查给定的类是否代表
// 一个原语(即boolean、byte、char、short、int、long、float或double)、void
// 或这些类型的包装器(即Boolean、Byte, Character, Short, Integer, Long, Float, Double, or Void)。
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}
注意:
- isPrimitiveOrWrapper方法中,void/Void也会返回true,所以在isSimpleValueType中一开始会单独判断。
- Enum、CharSequence、Number…这些都认为是简单类型
- autowire自动注入会忽略简单数据类型,但是@Autowire不会忽略。
PropertyDescriptor
属性描述器,java.beans提供的。 (java.beans.PropertyDescriptor)
java规范中,认为Bean的属性要有get和set方法
我们找下PropertyDescriptor是怎么生成的:
org.springframework.beans.BeanWrapper#getPropertyDescriptors //接口
org.springframework.beans.BeanWrapperImpl#getPropertyDescriptors
org.springframework.beans.BeanWrapperImpl#getCachedIntrospectionResults
org.springframework.beans.CachedIntrospectionResults#forClass
org.springframework.beans.CachedIntrospectionResults#CachedIntrospectionResults //构造方法
org.springframework.beans.CachedIntrospectionResults#getBeanInfo(java.lang.Class<?>)
org.springframework.beans.BeanInfoFactory#getBeanInfo //接口
org.springframework.beans.ExtendedBeanInfoFactory#getBeanInfo
java.beans.Introspector#getBeanInfo(java.lang.Class<?>) //从这里开始就是jdk提供的方法了
java.beans.Introspector#getBeanInfo()
java.beans.Introspector#getTargetPropertyInfo
java.beans.Introspector#getTargetPropertyInfo
private PropertyDescriptor[] getTargetPropertyInfo() {
// Check if the bean has its own BeanInfo that will provide
// explicit information.
// 检查bean是否有自己的BeanInfo来提供显式信息。 (支持自定义BeanInfo)
PropertyDescriptor[] explicitProperties = null;
if (explicitBeanInfo != null) {...}
//检查父类有没有自定义的BeanInfo来提供显式信息
if (explicitProperties == null && superBeanInfo != null) {...}
//检查额外的类信息(也是通过explicitBeanInfo,自定义BeanInfo提供的)
for (int i = 0; i < additionalBeanInfo.length; i++) {...}
//explicitProperties是自定义的,如果没有自定义指定,会利用反射解析获取属性信息
if (explicitProperties != null) {
// Add the explicit BeanInfo data to our results.
addPropertyDescriptors(explicitProperties);
} else {
// 如果没有自定义指定,会利用反射解析获取属性信息
// Apply some reflection to the current class.
// 否则对当前类应用反射进行解析
// First get an array of all the public methods at this level
// 获取所有public方法
Method methodList[] = getPublicDeclaredMethods(beanClass);
// Now analyze each method.
for (int i = 0; i < methodList.length; i++) {
Method method = methodList[i];
if (method == null) {
continue;
}
// skip static methods.
// 跳过静态方法
int mods = method.getModifiers();
if (Modifier.isStatic(mods)) {
continue;
}
//方法名
String name = method.getName();
//方法入参
Class<?>[] argTypes = method.getParameterTypes();
//方法返回值
Class<?> resultType = method.getReturnType();
int argCount = argTypes.length;
PropertyDescriptor pd = null;
//方法名长度小于3且不是is开头,肯定不属于规范的get/set方法
if (name.length() <= 3 && !name.startsWith(IS_PREFIX)) {
// Optimization. Don't bother with invalid propertyNames.
continue;
}
try {
//方法入参个数0的情况
if (argCount == 0) {
if (name.startsWith(GET_PREFIX)) {
// Simple getter
pd = new PropertyDescriptor(this.beanClass, name.substring(3), method, null);
} else if (resultType == boolean.class && name.startsWith(IS_PREFIX)) {
// Boolean getter
pd = new PropertyDescriptor(this.beanClass, name.substring(2), method, null);
}
}
//方法入参个数1的情况
else if (argCount == 1) {
if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
} else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
// Simple setter
pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
if (throwsException(method, PropertyVetoException.class)) {
pd.setConstrained(true);
}
}
}
//方法入参个数2的情况
else if (argCount == 2) {
if (void.class.equals(resultType) && int.class.equals(argTypes[0]) && name.startsWith(SET_PREFIX)) {
pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, null, method);
if (throwsException(method, PropertyVetoException.class)) {
pd.setConstrained(true);
}
}
}
} catch (IntrospectionException ex) {...}
if (pd != null) {
// If this class or one of its base classes is a PropertyChange
// source, then we assume that any properties we discover are "bound".
if (propertyChangeSource) {...}
addPropertyDescriptor(pd);
}
}
}
//通过合并属性描述符列表来填充属性描述符表。(属性分类合并)
// 按照java规范来说,一个属性至少有get/set两个方法,对于一个属性描述器
processPropertyDescriptors();
// Allocate and populate the result array.
PropertyDescriptor result[] =
properties.values().toArray(new PropertyDescriptor[properties.size()]);
// Set the default index.
if (defaultPropertyName != null) {...}
return result;
}
判断方法入参个数:
- 0个的情况:
- 方法名以"get"开头认为是get方法
- 方法名以"is"开头,且返回值为boolean类型认为是get方法
- 1个的情况:
- 入参类型为int,且方法名以"get"开头认为是get方法(IndexedPropertyDescriptor)
- 返回值类型为void,且方法名以"set"开头认为是set方法
- 2个的情况:
- 返回值类型为void,第一个入参类型为int,且方法名以"set"开头认为是set方法(IndexedPropertyDescriptor)
IndexedPropertyDescriptor:
- 描述了一个类似数组的属性,它具有索引读和/或索引写方法来访问数组的特定元素。
- 索引属性还可以提供简单的非索引读和写方法。如果存在,则读写. 索引read方法返回的类型 的数组。
简单概括就是:
-
get方法的定义是: 方法参数个数为0个,并且方法名字以"get"开头
或者 方法名字以"is"开头并 且方法的返回类型为boolean
-
set方法的定义是:方法参数个数为1个,方法名字以"set"开头,且方法返回类型为 void
所以getClass方法也被解析成了一个属性PropertyDescriptor
1.2 根据类型找结果
@Autowired注解也是用的这个方法,非常重要和复杂
这个方法下一节再讲,很复杂!!
2. @Autowired注解注入
注解注入的实现是依赖BeanPostProcessor的扩展机制实现的,即InstantiationAwareBeanPostProcessor
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
//2.@Autowired注解注入
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
//默认提供的实现里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法直接给对象中的属性赋值
// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
// AutowiredAnnotationBeanPostProcessor会处理@Autowired、@Value、 @Inject 注解
// CommonAnnotationBeanPostProcessor会处理@Resource注解
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {...}
pvs = pvsToUse;
}
}
InstantiationAwareBeanPostProcessor的实现中:
- AutowiredAnnotationBeanPostProcessor会处理@Autowired、@Value、 @Inject 注解
- CommonAnnotationBeanPostProcessor会处理@Resource注解
我们先分析AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor相对简单,逻辑也和@Autowired的差不多。
AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessors实现了两个接口:
其中SmartInstantiationAwareBeanPostProcessor继承于InstantiationAwareBeanPostProcessor,比它更强大:
以后讲,先不管。
看到它实现了两个接口:InstantiationAwareBeanPostProcessor(SmartInstantiationAwareBeanPostProcessor),MergedBeanDefinitionPostProcessor
按照Bean的生命周期流程的执行顺序:
- 我们先看MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition方法的实现
- 再看InstantiationAwareBeanPostProcessor.postProcessProperties方法的实现
postProcessMergedBeanDefinition:解析注入点并缓存
postProcessProperties:基于注入点属性注入
2.1 解析注入点并缓存
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
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.
// 首先快速检查并发map,尽量减少锁的范围。
// InjectionMetadata:封装了当前类中所有的注入点
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);
}
//解析注入点并缓存(被@Autowired标记的属性、方法..)
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
解析注入点:
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
//a. 判断当前类是否需要查找注入点(包路径是java.开头的类不需要找注入点)
//比如如果一个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 -> {
//b. field上是否存在@Autowired、@Value、@Inject其中的一个
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
//static field不是注入点,不会进行自动注入
//e.因为静态属性是属于类的,而不是属于对象的。
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {...}
return;
}
//c.判断是否要必须注入,针对@Autowired的required属性。
boolean required = determineRequiredStatus(ann);
//构造字段注入点
currElements.add(new AutowiredFieldElement(field, required));
}
});
//遍历targetClass中所有的Method
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//d.找到所提供的桥接方法的原始方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
//比较桥接方法和它桥接的方法的特征。如果参数和返回类型相同,则它是Java 6中引入的“可见性”桥接方法
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
//“可见性”桥接方法也会过滤
return;
}
//b. 判断method上是否存在@Autowired、@Value、@Inject其中的一个
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
//e.static method不是注入点,不会进行自动注入
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {...}
return;
}
//set方法最好有入参,做个日志提示(没有参数、1个参数、多个参数都可以)
//就算@Autowired标记的方法没有入参,Spring也会去执行,只是不会去找参数类型对应的实例
if (method.getParameterCount() == 0) {...}
//c.判断是否要必须注入,针对@Autowired的required属性。
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
//构造方法注入点
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
//do while循环,递归处理父类
while (targetClass != null && targetClass != Object.class);
//将所有注入点整体封装成一个对象返回
return InjectionMetadata.forElements(elements, clazz);
}
a. 判断当前类是否需要查找注入点
org.springframework.core.annotation.AnnotationUtils#isCandidateClass(java.lang.Class<?>, java.util.Collection<java.lang.Class<? extends java.lang.annotation.Annotation>>)
autowiredAnnotationTypes的值:
public static boolean isCandidateClass(Class<?> clazz, Collection<Class<? extends Annotation>> annotationTypes) {
//annotationTypes此时就是@Autowired、@Value、@Inject
for (Class<? extends Annotation> annotationType : annotationTypes) {
if (isCandidateClass(clazz, annotationType)) {
return true;
}
}
return false;
}
public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType) {
return isCandidateClass(clazz, annotationType.getName());
}
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
//注解名字是java.开头的,代表需要查找注入点
if (annotationName.startsWith("java.")) {
return true;
}
//什么情况下不需要找注入点呢?主要看这:
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
//默认true,大部分情况下类都是要找注入点的
return true;
}
org.springframework.core.annotation.AnnotationsScanner#hasPlainJavaAnnotationsOnly(java.lang.Class<?>)
static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
//java.开头的类不需要找注入点
return (type.getName().startsWith("java.") || type == Ordered.class);
}
b. 判断field/method上是否存在@Autowired、@Value、@Inject其中的一个
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
//获取指定元素上的所有注解和元注解。(默认不包括任何继承的注解)
MergedAnnotations annotations = MergedAnnotations.from(ao);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
其中autowiredAnnotationTypes值在构造函数里初始化了:@Autowired、@Value、@Inject
c. 判断是否要必须注入,针对@Autowired的required属性
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineRequiredStatus(org.springframework.core.annotation.MergedAnnotation<?>)
protected boolean determineRequiredStatus(MergedAnnotation<?> ann) {
//调用MergedAnnotation.asMap方法,传入lambda表达式的一个对象,生成AnnotationAttributes对象
return determineRequiredStatus(ann.<AnnotationAttributes> asMap(
mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
}
protected boolean determineRequiredStatus(AnnotationAttributes ann) {
//requiredParameterName="required"
//requiredParameterValue=true
//判断注解上是否包含required属性,并且是否为true
return (!ann.containsKey(this.requiredParameterName) ||
this.requiredParameterValue == ann.getBoolean(this.requiredParameterName));
}
d. 找到所提供的桥接方法的原始方法
什么情况下会有桥接方法?
public interface UserInterface<T> {
void setOrderService(T t);
}
@Component
public class UserService implements UserInterface<OrderService> {
private OrderService orderService;
@Override
@Autowired
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
public void test() {
System.out.println("test123");
}
}
此时这段代码应该只有一个注入点,但是我们看下UserService对应的字节码:
可以看到在UserSerivce的字节码中有两个setOrderService方法:
- public setOrderService(Lcom/zhouyu/service/OrderService;)V
- public synthetic bridge setOrderService(Ljava/lang/Object;)V
并且都是存在@Autowired注解的。
java字节码层面针对泛型方法,就会特殊处理生成一个synthetic bridge的方法
java泛型,翻译成字节码,底层其实就是一个Object类型。(泛型、桥接方法、泛型擦除)
简单通过反射就会拿到两个方法,所以在Spring中需要处理这种情况,当遍历到桥接方法时,得找到原方法。
e. static的字段或方法为什么不支持
Demo演示:
@Component
@Scope("prototype")
public class OrderService {
}
@Component
@Scope("prototype")
public class UserService {
@Autowired
private static OrderService orderService;
public void test() {
System.out.println("test123");
}
}
看上面代码,UserService和OrderService都是原型Bean,假设Spring支持static字段进行自动注入,那么现在调用两次
- UserService userService1 = context.getBean(“userService”)
- UserService userService2 = context.getBean(“userService”)
问此时,userService1的orderService值是什么?还是它自己注入的值吗?
答案是不是,一旦userService2 创建好了之后,static orderService字段的值就发生了修改了,从而出现bug。
2.2 基于注入点属性注入
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//找注入点(所有被@Autowired注解了的Field或Method)
//findAutowiringMetadata方法在上一步,BeanDefinition的后置流程中已经执行过了,所以此时直接从缓存拿了
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
//注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {...}
catch (Throwable ex) {...}
return pvs;
}
org.springframework.beans.factory.annotation.InjectionMetadata#inject
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);
}
}
}
方法和字段注入点对应的类型:
a. 字段注入
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
//缓存,一开始肯定没有缓存
if (this.cached) {...}
else {
//根据field从BeanFactory中查到匹配的Bean对象
value = resolveFieldValue(field, bean, beanName);
}
//反射给field赋值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
resolveFieldValue:关于怎么找的,比较复杂,下一节再说。
b.方法注入
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//如果pvs中已经有当前注入点的值了,则跳过注入(autowire注入、set方法注入的优先级更高)
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
Object[] arguments;
//缓存,一开始肯定没有缓存
if (this.cached) {...}
else {
//根据方法信息找值,@Autowired注解标记的方法允许多个参数
//怎么找下一节再说。
arguments = resolveMethodArguments(method, bean, beanName);
}
if (arguments != null) {
try {
//反射调方法
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {...}
}
}
3. PropertyValues手动注入
把pvs(PropertyValues属性)里的属性值给bean进行赋值!
- 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
- 通过pvs里的属性值给bean进行赋值,需要提供写方法才生效
PropertyValues怎么设置?
- pvs里的属性值可以利用autowire自动注入的方式收集
- 也可以手动设置(优先级最高),比如可以通过以下方式设置让属性赋值生效:
applyPropertyValues 方法的主要逻辑是遍历 bd.propertyValues 中的 PropertyValue 属性,根据引用类型提取出对象实例,再将这个对象实例转换成可以直接注入的实例。
- 解析对象:valueResolver.resolveValueIfNecessary(pv, originalValue) 将 pv.value 解析成实例对象。
- 类型转换:convertForProperty(resolvedValue, propertyName, bw, converter) 将 resolvedValue 转换成可直接进行类型注入的类型。
- 依赖注入: bw.setPropertyValues(mpvs) 将解析后的属性注入到 bw 实例中
- 结果缓存:Spring 会将 valueResolver 和 converter 解析后的最终对象缓存到 pv 中,提高效率。如果全部 pv 都不需要重新解析,则设置 mpvs.converted=true。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {...}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
//1.获取List<PropertyValue>,如果已经解析过,则直接注入后返回
//通常来说,默认实现就是MutablePropertyValues
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
//isConverted:返回该holder是否只包含转换后的值(true),或者值是否仍然需要转换(false)。
//MutablePropertyValues已经解析,直接注入,在方法解析后会缓存已经解析的PropertyValue
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
// BeanWrapper属性注入
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {...}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
//类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//BeanDefinitionValueResolver:解析器,用于解析PropertyValue,如间接引用替换成直接对象
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
//2.逐个解析、转换PropertyValue
// Create a deep copy, resolving any references for values.
// 创建一个深度拷贝,解析值的任何引用。
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();
//标记位,实际使用resolveDependency方法查找依赖注入的对象
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);
}
//2.1 解析对象
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
//2.2 类型转换
Object convertedValue = resolvedValue;
//是否可转换
// 检查属性是否可写,必须有写方法(setter method)
// 检查给定的属性路径是否指示索引或嵌套属性。比如user.name[0],这种就不行
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
//转换器转换后的值
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
//3. 缓存解析后的PropertyValue:resolvedValue -> convertedValue
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
//3.1 缓存情况1:解析后的对象实例没有被替换(地址匹配):如动态代理等,会直接替换对象。
if (resolvedValue == originalValue) {
if (convertible) {
//可转换的,记录转换后的值
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
//3.2 缓存情况2:如果是可转换的,对象类型是TypedStringValue且不需要动态转换、转换后不是集合或数组
// originalValue如果是TypedStringValue,则类型转换器会将String转换成指定类型targetType
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
//3.3 不缓存:每次都重新解析
else {
resolveNecessary = true;
//最终的值放到deepCopy
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
//所有的字段都能成功解析,不会再变,才会标记mpvs为转换完成,否则下次还需要动态解析
//也可能是mpvs包含的部分字段需要解析
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
//BeanWrapper属性注入
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {...}
}
BeanDefinitionValueResolver
BeanDefinitionValueResolver#resolveValueIfNecessary(argName, value) 方法功能:解析 value 的真实类型,value 的类型不同,处理的结果也不同。本质就是进行依赖查找。
- RuntimeBeanReference 类型:引用类型,根据 ref.beanType 或 ref.beanName 从容器中获取。
- RuntimeBeanNameReference 类型:Spring EL 表达式解析 ref.beanName。
- BeanDefinitionHolder 或 BeanDefinition 类型:根据 BeanDefinition 实例化 bean。
- DependencyDescriptor:采用 beanFactory#resolveDependency 进行依赖查找。
- ManagedList 等集合类型:规则和上述完全类似,只是返回集合而已。
- 其它类型:如果是 String,则 Spring EL 表达式解析,其余的直接返回 originalValue。
如 applyPropertyValues 中的 AutowiredPropertyMarker.INSTANCE 类型:表示使用 beanFactory#resolveDependency 进行依赖查找。BeanDefinitionBuilder 添加属性时就会使用时这些类型。
BeanWrapper属性注入
BeanWrapper:对 Bean 操作的封装,如 JavaBean 的内省,属性的设置。其 bw.setPropertyValues(mpvs) 将属性注入到 bean 实例中。
- BeanWrapperImpl:(默认)采用 PropertyDescriptor 进行注入,也就是 setter 方法反射注入,对应的处理器为 BeanPropertyHandler。
- DirectFieldAccessor:采用字段注入,对应的处理器为 FieldPropertyHandler。
核心代码:
org.springframework.beans.BeanWrapperImpl.BeanPropertyHandler#setValue
public void setValue(@Nullable Object value) throws Exception {
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
if (System.getSecurityManager() != null) {...}
else {
ReflectionUtils.makeAccessible(writeMethod);
writeMethod.invoke(getWrappedInstance(), value);
}
}
反射set方法赋值。