原创:JoonWhee 程序员囧辉
前言
在 Spring IoC:createBean 详解(上)-1 中代码块4.5 和 Spring IoC:createBean 详解(下)-1 中代码块1、代码块4的 7.1.1 我们遗留了一个解析——@Autowire 注解的解析。之所以单独提出来,是因为在我现在接触的项目中,使用 @Autowire 注解的比例非常高,可以说基本用过 Spring 的同学都接触过这个注解,重要性不言而喻。因此,单独拿出来,较详细的介绍一下。
本文只会单独介绍 @Autowire 的部分内容,具体 @Autowire 注解的完整过程,需要结合 Spring IoC:createBean 详解(上)-1 中代码块4.5 和 Spring IoC:createBean 详解(下)-1 中代码块1、代码块4的 7.1.1 去看。
如何使用
1.开启注解配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- component-scan包含了annotation-config的效果 -->
<context:component-scan base-package="com.joonwhee.open.demo.service"/>
<context:annotation-config/>
</beans>
要使用 @Autowire 注解,可以通过 <context:component-scan /> 或 <context:annotation-config/> 来开启,其中前者是包含了后者的效果的,因此现在一般都使用 <context:component-scan /> 即可。
2.在代码中使用
@Service
public class ConstructorServiceImpl implements ConstructorService {
// 1.属性注入
@Autowired
private UserService userService;
private final DemoService demoService;
// 2.构造函数注入
@Autowired
public ConstructorServiceImpl(DemoService demoService) {
this.demoService = demoService;
}
}
该代码中使用了目前最常见的两种注入方式:1)属性注入;2)构造函数注入。
以我自己为例,我周围最常用的是:属性注入,但是 Spring 团队建议使用的方式是:构造函数注入,当你使用属性注入时,鼠标移到属性上的 @Autowire 就可以看到如下图的提示,并且可以通过快捷键将属性注入直接修改成构造函数注入。
构造函数的常见优点是:
- 保证依赖不可变(final 关键字)
- 保证依赖不为空(省去了检查)
- 以完全初始化的状态返回到客户端(调用)代码
- 避免了循环依赖
- 提升了代码的可复用性
构造函数的常见缺点是:
- 构造函数会有很多参数。
- 有些类是需要默认构造函数的,一旦使用构造函数注入,就无法使用默认构造函数。
- 这个类里面的有些方法并不需要用到这些依赖。
这些优点我看了下,个人觉得还好,只要不瞎用,其实使用属性注入并不会有什么问题。至于使用哪一种,就看个人喜好了。
继承结构
@Autowire 注解的功能实现都是由 AutowiredAnnotationBeanPostProcessor 实现,AutowiredAnnotationBeanPostProcessor 的继承关系如下图:
源码解析
AutowiredAnnotationBeanPostProcessor 何时被注册到 BeanFactory?
在 Spring IoC:context:component-scan 节点详解 中的代码块17就有 AutowiredAnnotationBeanPostProcessor 被注册到 BeanFactory 的代码,如下。
AnnotationConfigUtils#registerAnnotationConfigProcessors
查看该方法的上下文,请参考:Spring IoC:context:component-scan 节点详解 中的代码块17。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// 1.设置dependencyComparator属性
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// 2.设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象)
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
// 3.注册内部管理的用于处理@Configuration注解的后置处理器的bean
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 3.1 registerPostProcessor: 注册BeanDefinition到注册表中
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 4.注册内部管理的用于处理@Autowired、@Value、@Inject以及@Lookup注解的后置处理器的bean
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 5.注册内部管理的用于处理@Required注解的后置处理器的bean
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 6.注册内部管理的用于处理JSR-250注解(例如@Resource, @PostConstruct, @PreDestroy)的后置处理器的bean
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 7.注册内部管理的用于处理JPA注解的后置处理器的bean
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 8.注册内部管理的用于处理@EventListener注解的后置处理器的bean
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
// 9.注册内部管理用于生产ApplicationListener对象的EventListenerFactory对象
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
在该代码的第4点注册了 AutowiredAnnotationBeanPostProcessor,具体看 registerAnnotationConfigProcessors 方法的调用方,可以看到 AnnotationConfigBeanDefinitionParser 和 ComponentScanBeanDefinitionParser,而这两个正是 <context:component-scan /> 和 <context:annotation-config/> 的 bean 定义解析器。
构造函数注入时做了什么
构造函数注入通常来说有两种:1)xml 配置注入;2)@Autowire 注解注入;本文只讨论 @Autowire 注解注入。
AutowiredAnnotationBeanPostProcessor 中重写的方法不多,直接找一下就可以找到跟构造函数相关的方法:determineCandidateConstructors,该方法被定义在 SmartInstantiationAwareBeanPostProcessor 接口中,主要作用是:确定要用于给定 bean 的候选构造函数。
在 Spring IoC 的过程中,调用的入口在 Spring IoC:createBean 详解(上)-1 中的代码块4.5,下面介绍下 determineCandidateConstructors 方法。
AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors
查看该方法的上下文,请参考:Spring IoC:createBean 详解(上)-1 中的代码块4.5。
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here..
// @Lookup注解检查
if (!this.lookupMethodsChecked.contains(beanName)) {
try {
ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(beanName,
"Cannot apply @Lookup to beans without corresponding bean definition");
}
}
}
});
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
} catch (NoClassDefFoundError err) {
throw new BeanCreationException(beanName, "Failed to introspect bean class [" + beanClass.getName() +
"] for lookup method metadata: could not find class that it depends on", err);
}
// 已经检查过的添加到lookupMethodsChecked
this.lookupMethodsChecked.add(beanName);
}
// Quick check on the concurrent map first, with minimal locking.
// 1.构造函数解析,首先检查是否存在于缓存中
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
// Fully synchronized resolution now...
// 2.加锁进行操作
synchronized (this.candidateConstructorsCache) {
// 3.再次检查缓存,双重检测
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
// 存放原始的构造函数(候选者)
Constructor<?>[] rawCandidates;
try {
// 4.获取beanClass声明的构造函数(如果没有声明,会返回一个默认的无参构造函数)
rawCandidates = beanClass.getDeclaredConstructors();
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
// 存放使用了@Autowire注解的构造函数
List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
// 存放使用了@Autowire注解,并且require=true的构造函数
Constructor<?> requiredConstructor = null;
// 存放默认的构造函数
Constructor<?> defaultConstructor = null;
// 5.遍历原始的构造函数候选者
for (Constructor<?> candidate : rawCandidates) {
// 6.获取候选者的注解属性
AnnotationAttributes ann = findAutowiredAnnotation(candidate);
if (ann == null) {
// 7.如果没有从候选者找到注解,则尝试解析beanClass的原始类(针对CGLIB代理)
Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
} catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
// 8.如果该候选者使用了@Autowire注解
if (ann != null) {
if (requiredConstructor != null) {
// 8.1 之前已经存在使用@Autowired(required = true)的构造函数,则不能存在其他使用@Autowire注解的构造函数,否则抛异常
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
// 8.2 获取注解的require属性值
boolean required = determineRequiredStatus(ann);
if (required) {
if (!candidates.isEmpty()) {
// 8.3 如果当前候选者是@Autowired(required = true),则之前不能存在其他使用@Autowire注解的构造函数,否则抛异常
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
// 8.4 如果该候选者使用的注解的required属性为true,赋值给requiredConstructor
requiredConstructor = candidate;
}
// 8.5 将使用了@Autowire注解的候选者添加到candidates
candidates.add(candidate);
} else if (candidate.getParameterTypes().length == 0) {
// 8.6 如果没有使用注解,并且没有参数,则为默认的构造函数
defaultConstructor = candidate;
}
}
// 9.如果存在使用了@Autowire注解的构造函数
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
// 9.1 但是没有使用了@Autowire注解并且required属性为true的构造函数
if (requiredConstructor == null) {
if (defaultConstructor != null) {
// 9.2 如果存在默认的构造函数,则将默认的构造函数添加到candidates
candidates.add(defaultConstructor);
} else if (candidates.size() == 1 && logger.isWarnEnabled()) {
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
// 9.3 将所有的candidates当作候选者
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
} else if (rawCandidates.length == 1 && rawCandidates[0].getParameterTypes().length > 0) {
// 10.如果candidates为空 && beanClass只有一个声明的构造函数(非默认构造函数),则将该声明的构造函数作为候选者
candidateConstructors = new Constructor<?>[]{rawCandidates[0]};
} else {
// 11.否则返回一个空的Constructor对象
candidateConstructors = new Constructor<?>[0];
}
// 12.将beanClass的构造函数解析结果放到缓存
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
// 13.返回解析的构造函数
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
6.获取候选者的注解属性,见代码块1详解。
关于 8.1 和 8.3 的异常校验,说的简单点:在一个 bean 中,只要有构造函数使用了 “@Autowired(required = true)” 或 “@Autowired”,就不允许有其他的构造函数使用 “@Autowire”;但是允许有多个构造函数同时使用 “@Autowired(required = false)”。
代码块1:findAutowiredAnnotation
private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
// 1.判断ao是否有被注解修饰
if (ao.getAnnotations().length > 0) {
// 2.检查是否有autowiredAnnotationTypes中的注解:@Autowired、@Value(@Value无法修饰构造函数)
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
// 3.拿到注解的合并注解属性,@Autowire在这边拿到,required=true(默认属性)
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
if (attributes != null) {
return attributes;
}
}
}
return null;
}
确定了要用于给定 bean 的候选构造函数后,之后的逻辑就是执行构造函数自动注入,该逻辑在 Spring IoC:createBean 详解(上)-1 中的代码块5已经介绍。
属性注入时做了什么
属性注入通常来说有两种:1)xml 配置注入;2)@Autowire 注解注入;本文只讨论 @Autowire 注解注入。
AutowiredAnnotationBeanPostProcessor 中跟属性注入有关的方法出口有两个:postProcessMergedBeanDefinition 和 postProcessPropertyValues。
1.postProcessMergedBeanDefinition 方法介绍
postProcessMergedBeanDefinition 被定义在 MergedBeanDefinitionPostProcessor 接口中,
该方法的主要作用是:对指定 bean 的给定 MergedBeanDefinition 进行后置处理。
在 AutowiredAnnotationBeanPostProcessor 的实现中,主要是对使用了 @Autowire 注解的方法和属性进行预解析,并放到 injectionMetadataCache 缓存中,用于后续使用。
在 Spring IoC 的过程中,调用的入口在:Spring IoC:createBean 详解(下)-1 中的代码块1,下面介绍下 postProcessMergedBeanDefinition 方法。
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
查看该方法的上下文,请参考:Spring IoC:createBean 详解(下)-1 中的代码块1。
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (beanType != null) {
// 1.在指定Bean中查找使用@Autowire注解的元数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
// 2.检查元数据中的注解信息
metadata.checkConfigMembers(beanDefinition);
}
}
1.在指定 bean 中查找使用 @Autowire 注解的元数据,见代码块2详解。
2.检查元数据中的注解信息,见代码块4详解。
代码块2:findAutowiringMetadata
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
// 1.设置cacheKey的值(beanName 或者 className)
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 2.检查beanName对应的InjectionMetadata是否已经存在于缓存中
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 3.检查InjectionMetadata是否需要刷新(为空或者class变了)
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
// 4.加锁后,再次从缓存中获取beanName对应的InjectionMetadata
metadata = this.injectionMetadataCache.get(cacheKey);
// 5.加锁后,再次检查InjectionMetadata是否需要刷新
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
// 6.如果需要刷新,并且metadata不为空,则先移除
metadata.clear(pvs);
}
try {
// 7.解析@Autowired注解的信息,生成元数据(包含clazz和clazz里解析到的注入的元素,
// 这里的元素包括AutowiredFieldElement和AutowiredMethodElement)
metadata = buildAutowiringMetadata(clazz);
// 8.将解析的元数据放到injectionMetadataCache缓存,以备复用,每一个类只解析一次
this.injectionMetadataCache.put(cacheKey, metadata);
} catch (NoClassDefFoundError err) {
throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
"] for autowiring metadata: could not find class that it depends on", err);
}
}
}
}
return metadata;
}
7.解析 @Autowired 注解的信息,生成元数据,见代码块3详解。
代码块3:buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
// 1.用于存放所有解析到的注入的元素的变量
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
Class<?> targetClass = clazz;
// 2.循环遍历
do {
// 2.1 定义存放当前循环的Class注入的元素(有序)
final LinkedList<InjectionMetadata.InjectedElement> currElements =
new LinkedList<InjectionMetadata.InjectedElement>();
// 2.2 如果targetClass的属性上有@Autowired注解,则用工具类获取注解信息
ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
// 2.2.1 获取field上的@Autowired注解信息
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
// 2.2.2 校验field是否被static修饰,如果是则直接返回,因为@Autowired注解不支持static修饰的field
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 2.2.3 获取@Autowired注解的required的属性值(required:值为true时,如果没有找到bean时,自动装配应该失败;false则不会)
boolean required = determineRequiredStatus(ann);
// 2.2.4 将field、required封装成AutowiredFieldElement,添加到currElements
currElements.add(new AutowiredFieldElement(field, required));
}
}
});
// 2.3 如果targetClass的方法上有@Autowired注解,则用工具类获取注解信息
ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
// 2.3.1 找到桥接方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
// 2.3.2 判断方法的可见性,如果不可见则直接返回
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
// 2.3.3 获取method上的@Autowired注解信息
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// 2.3.4 校验method是否被static修饰,如果是则直接返回,因为@Autowired注解不支持static修饰的method
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
// 2.3.5 @Autowired注解标识在方法上的目的就是将容器内的Bean注入到方法的参数中,没有参数就违背了初衷
if (method.getParameterTypes().length == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
// 2.3.6 获取@Autowired注解的required的属性值
boolean required = determineRequiredStatus(ann);
// 2.3.7 获取method的属性描述器
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 2.3.8 将method、required、pd封装成AutowiredMethodElement,添加到currElements
currElements.add(new AutowiredMethodElement(method, required, pd));
}
}
});
// 2.4 将本次循环获取到的注解信息添加到elements
elements.addAll(0, currElements);
// 2.5 在解析完targetClass之后,递归解析父类,将所有的@Autowired的属性和方法收集起来,且类的层级越高其属性会被越优先注入
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class); // 2.6 递归解析targetClass父类(直至父类为Object结束)
// 2.7 将clazz和解析到的注入的元素封装成InjectionMetadata
return new InjectionMetadata(clazz, elements);
}
2.2.1 获取 field 上的 @Autowired 注解信息、2.3.3 获取 method 上的 @Autowired 注解信息,见代码块1详解。
代码块4:checkConfigMembers
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
Set<InjectedElement> checkedElements = new LinkedHashSet<InjectedElement>(this.injectedElements.size());
// 1.遍历检查所有要注入的元素
for (InjectedElement element : this.injectedElements) {
Member member = element.getMember();
// 2.如果beanDefinition的externallyManagedConfigMembers属性不包含该member
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
// 3.将该member添加到beanDefinition的externallyManagedConfigMembers属性
beanDefinition.registerExternallyManagedConfigMember(member);
// 4.并将element添加到checkedElements
checkedElements.add(element);
if (logger.isDebugEnabled()) {
logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
}
}
}
// 5.赋值给checkedElements(检查过的元素)
this.checkedElements = checkedElements;
}
至此,使用 @Autowire 修饰的方法和属性的相关元数据信息都已经放到 injectionMetadataCache 缓存中,用于后续使用,其实主要就是下面的 postProcessPropertyValues 方法使用。
2.postProcessPropertyValues 方法介绍
postProcessPropertyValues 被定义在 InstantiationAwareBeanPostProcessor 接口中,该方法的主要作用是:将属性值应用于给定 bean 之前对给定属性值进行后置处理。
在 AutowiredAnnotationBeanPostProcessor 的实现中,主要是对使用了 @Autowire 注解的方法和属性进行自动注入,将依赖的 bean 赋值给对应的属性。
在 Spring IoC 的过程中,调用的入口在:Spring IoC:createBean 详解(下)-1 中的代码块4中的7.1.1,下面介绍下 postProcessPropertyValues 方法。
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
查看该方法的上下文,请参考:Spring IoC:createBean 详解(下)-1 中的代码块4中的7.1.1。
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
// 1.在指定Bean中查找使用@Autowire注解的元数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 2.InjectionMetadata: 执行inject()方法,开始执行属性注入或方法注入
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;
}
1.在指定 bean 中查找使用 @Autowire 注解的元数据,见代码块2详解。
2.执行 inject() 方法,开始执行属性注入或方法注入,见代码块5详解。
代码块5:inject
public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
// 1.如果checkedElements存在,则使用checkedElements,否则使用injectedElements
Collection<InjectedElement> elementsToIterate =
(this.checkedElements != null ? this.checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (InjectedElement element : elementsToIterate) {
if (debug) {
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
// 2.解析@Autowired注解生成的元数据类:AutowiredFieldElement、AutowiredMethodElement,
// 这两个类继承InjectionMetadata.InjectedElement,各自重写了inject方法。
element.inject(target, beanName, pvs);
}
}
}
2.解析 @Autowired 注解生成的元数据类:AutowiredFieldElement、AutowiredMethodElement,这两个类继承InjectionMetadata.InjectedElement,各自重写了 inject 方法。对于属性注入来说,会走到 AutowiredFieldElement 中的 inject 方法,见代码块6详解。
代码块6:AutowiredFieldElement#inject
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
// 1.拿到该元数据的属性值
Field field = (Field) this.member;
Object value;
// 2.如果缓存中已经存在,则直接从缓存中解析属性
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
} else {
// 3.将field封装成DependencyDescriptor
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 4.解析当前属性所匹配的bean实例,并把解析到的bean实例的beanName存储在autowiredBeanNames中
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
// 5.value不为空或者required为true
if (value != null || this.required) {
// 6.如果属性依赖注入的bean不止一个(Array,Collection,Map),缓存cachedFieldValue放的是DependencyDescriptor
this.cachedFieldValue = desc;
// 7.注册依赖关系到缓存(beanName 依赖 autowiredBeanNames)
registerDependentBeans(beanName, autowiredBeanNames);
// 8.如果属性依赖注入的bean只有一个(正常都是一个)
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
// @Autowired标识属性类型和Bean的类型要匹配,因此Array,Collection,Map类型的属性不支持缓存属性Bean名称
// 9.检查autowiredBeanName对应的bean的类型是否为field的类型
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
// 10.将该属性解析到的bean的信息封装成ShortcutDependencyDescriptor,
// 以便之后可以通过getBean方法来快速拿到bean实例
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
} else {
this.cachedFieldValue = null;
}
// 11.缓存标识设为true
this.cached = true;
}
}
}
if (value != null) {
// 12.设置字段访问性
ReflectionUtils.makeAccessible(field);
// 13.通过反射为属性赋值,将解析出来的bean实例赋值给field
field.set(bean, value);
}
}
4.解析当前属性所匹配的 bean 实例,并把解析到的 bean 实例的 beanName 存储在 autowiredBeanNames 中,见 Spring IoC:createBean 详解(上)-2 中代码块9详解。
7.注册依赖关系到缓存(beanName 依赖 autowiredBeanNames),见代码块7详解。
13.通过反射为属性赋值,将解析出来的 bean 实例赋值给 field,至此,@Autowire 修饰的 bean 就被注入进来了。
代码块7:registerDependentBeans
private void registerDependentBeans(String beanName, Set<String> autowiredBeanNames) {
if (beanName != null) {
// 1.遍历所有autowiredBeanNames
for (String autowiredBeanName : autowiredBeanNames) {
if (this.beanFactory.containsBean(autowiredBeanName)) {
// 2.如果autowiredBeanName在BeanFactory中存在,则注册依赖关系到缓存(beanName 依赖 autowiredBeanName)
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
}
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' to bean named '" + autowiredBeanName + "'");
}
}
}
}
2.如果 autowiredBeanName 在 BeanFactory 中存在,则注册依赖关系到缓存(beanName 依赖 autowiredBeanName),见 Spring IoC:getBean 详解 中代码块7详解。