文章目录
- spring5.3 六:依赖注入源码分析上
- spring的自动注入
- @Autowired自动注入
spring5.3 六:依赖注入源码分析上
之前分析了bean的生命周期各个阶段,下面针对自动注入和属性填充这个阶段进行详细分析。先来看下这部分源码
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
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;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 实例化之后,属性设置之前
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
//这个if 会根据配置的AUTOWIRE_BY_NAME 还是 AUTOWIRE_BY_TYPE 进行属性注入
//但是这跟AUTOWIRE注解没有关系 一般来说也不会进入到这个方法中 基本可以忽略
//PropertyValues 是RootBeanDefinition的一个属性
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// MutablePropertyValues是PropertyValues具体的实现类
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
//大致过程:找到bean当中需要属性注入的属性 然后记录到RootBeanDefinition的PropertyValues属性中
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
//和上面ByName方法类似
autowireByType(beanName, mbd, bw, 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();
}
//从这里开始处理@Autowired和@Resource
// 处理@Autowired 的是AutowiredAnnotationBeanPostProcessor
// 处理@Resource 的是CommonAnnotationBeanPostProcessor
//它们都是InstantiationAwareBeanPostProcessor的实现类
//开始遍历InstantiationAwareBeanPostProcessor这个接口的实现类
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
// AutowiredAnnotationBeanPostProcessor在调用postProcessProperties()之前会先调用postProcessMergedBeanDefinition方法
//AutowiredAnnotationBeanPostProcessor 不仅实现了InstantiationAwareBeanPostProcessor 也实现了MergedBeanDefinitionPostProcessor
//而postProcessMergedBeanDefinition 是MergedBeanDefinitionPostProcessor 提供的接口
// 而MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition是处理合并后的BeanDefinition,
// 也就是在在实例化后这个步骤前进行调用,那么自然也就在属性赋值前就已经调用了
// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
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);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
if (pvs != null) {
//进行属性赋值
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
这段代码主要分为两个部分,一个部分是spring自己的自动注入,就是这个if if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE)
。另一部分是注解的形式例如@Autowired和@Resource。
先来看第一部分
spring的自动注入
这一部分的内容都在if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE)
这个if当中,这部分的代码和@Autowired和@Resource无关,什么时候会执行这部分的代码呢?如下图
这种方式已经过期了。稍微了解就好。以BY_NAME作为例子,那么就会进入到autowireByName(beanName, mbd, bw, newPvs);
这个方法中
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取当前Bean中能进行自动注入的属性名
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 遍历每个属性名,并去获取Bean对象,并设置到pvs中
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
//通过getBean方法通过名称获取到对应的bean
Object bean = getBean(propertyName);
//将找到的bean对象保存到pvs当中 并没有直接赋值 这个对象是上面getBean方法返回的
// 比如说有个User对象需要注入 那么getBean返回的就是user对象 但是并没有直接赋值而是保存起来
pvs.add(propertyName, bean);
// 记录一下propertyName对应的Bean被beanName给依赖了
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
//忽略
}
else {
//忽略
}
}
}
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues();
//属性描述 set get方法的属性相关信息 比如说 set get方法名 属性名等等
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
// 什么样的属性能进行自动注入?
// 1.该属性有对应的set方法 pd.getWriteMethod() != null
// 2.没有在ignoredDependencyTypes中
// 3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
// 4.属性类型不是简单类型,比如int、Integer、int[] !BeanUtils.isSimpleProperty(pd.getPropertyType())
// 5.BeanDefinition中的PropertyValues 中不包含这个属性 !pvs.contains(pd.getName()) 如果包含了说明之前人为的进行赋值操作
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);
}
这部分内容就是说当类型设置为Autowire.BY_NAME时,就会进入autowireByName
方法,然后通过unsatisfiedNonSimpleProperties
方法找到那些属性是需要自动注入的,说白了就是找set方法,set后面的名称就是属性名称,遍历所有找到的名称通过getBean方法获取对应的bean然后放入到RootBeanDefinition。
autowireByType也类似,找到所有需要自动注入的属性名称后在找到对应的类型,然后根据类型找到对应的bean放入到RootBeanDefinition中。最后真正赋值的操作是applyPropertyValues(beanName, mbd, bw, pvs);
这部分。
@Autowired自动注入
@Autowired注解可以写在:
- 属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定一个
- 构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
- set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
从开头的populateBean源码来看@Autowired和@Resource的自动注入根据InstantiationAwareBeanPostProcessor的子类来实现的。
@Autowired实现的子类是AutowiredAnnotationBeanPostProcessor
@Resource实现的子类是CommonAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor
实现了SmartInstantiationAwareBeanPostProcessor
,MergedBeanDefinitionPostProcessor
等接口,其中MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition
方法在BeanDefinition后置处理是就执行。InstantiationAwareBeanPostProcessor的postProcessProperties
方法就是在这个阶段执行,也就是说先执行postProcessMergedBeanDefinition
方法。
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//找注入点
//大致过程:根据beanName 找到类对象 对类对象处理 找到符合条件的属性和方法
//把找到的注入点缓存起来
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
//findAutowiringMetadata的核心代码是buildAutowiringMetadata(clazz)
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//判断这个类需不需要找注入点 想String这种类型就不需要找注入点
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
//这个do while 中分为两个大步骤
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 1.遍历targetClass中的所有Field 每个Field执行lambda
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// field上是否存在@Autowired、@Value、@Inject中的其中一个
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
// ann != null 说明这个field有 上面三个注解之一
// 继续判断 如果这个field是static类型的 那么filed不是注入点,不会进行自动注入
//为什么静态不注入 从原型bean角度考虑
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 专门处理@Autowired的required的值
boolean required = determineRequiredStatus(ann);
//把这个注入点封装成AutowiredFieldElement 添加到currElements中
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 2.遍历targetClass中的所有Method 每个方法执行lambda
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//判断是不是桥接方法 然后对桥接方法的处理 过滤调桥接方法 这跟泛型有关 不管啦
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);
}
}
//同样解析@Autowired的required的值
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
//把这个注入点封装成AutowiredMethodElement 添加到currElements中
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
//把所有符合上面条件的Feild 和 method 放入到elements 中
elements.addAll(0, currElements);
//然后遍历父类 如果没有父类 那么while条件就不满足 退出循环
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
//判断获取到注解符不符合autowiredAnnotationTypes ,autowiredAnnotationTypes这是个集合
// 在创建AutowiredAnnotationBeanPostProcessor的时候 会调用AutowiredAnnotationBeanPostProcessor的构造方法
// 这个构造方法就会对autowiredAnnotationTypes 进行赋值 传入@Autowired @Value @Inject
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
//return 就表示了只要找到上面三个注解中某一个就会直接返回
return annotation;
}
}
return null;
}
总的来说在BeanDefinition后置处理的阶段会先执行AutowiredAnnotationBeanPostProcessor
的postProcessMergedBeanDefinition
方法。这个方法主要是找注入点(被@vaule、@Autowired标注的属性和方法)。是怎么找的呢?
过滤掉String、Integer等简单的类型。遍历每个类型的属性和方法通过findAutowiredAnnotation
找到注入点。把所有注入点都找到封装成一个对象放入到list中。
到了属性自动注入阶段执行AutowiredAnnotationBeanPostProcessor
的postProcessProperties
方法。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 找注入点(所有被@Autowired注解了的Field或Method)
// 把在BeanDefinition后置处理的阶段找到的注入点在拿出来
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);
}
}
}
第一个是给属性赋值的,第二个是给方法赋值的
AutowiredFieldElement
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
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);
}
}
AutowiredMethodElement
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//当前bean的BeanDefinition的PropertyValues属性 有没有当前注入点的值 大概是这个意思吧
// 没太搞懂 只是个判断 不管了
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();
}
}
}
通过上述的inject方法最后都是通过反射进行赋值。到此依赖注入部分就分析完了,但是如何根据属性找到具体的bean和如何根据方法找到对应的参数下篇在分析。