该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读
Spring 版本:5.1.14.RELEASE
开始阅读这一系列文章之前,建议先查看《深入了解 Spring IoC(面试题)》这一篇文章
该系列其他文章请查看:《死磕 Spring 之 IoC 篇 – 文章导读》
@Autowired 等注解的实现原理
在上一篇《Bean 的属性填充阶段》文章中讲到,在创建一个 Bean 的实例对象后,会对这个 Bean 进行属性填充。在属性填充的过程中,获取到已定义的属性值,然后会通过 InstantiationAwareBeanPostProcessor 对该属性值进行处理,最后通过反射机制将属性值设置到这个 Bean 中。在 Spring 内部有以下两个 InstantiationAwareBeanPostProcessor 处理器:
- AutowiredAnnotationBeanPostProcessor,解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值
- CommonAnnotationBeanPostProcessor,会解析 @Resource 注解标注的属性,获取对应的属性值
本文将会分析这两个处理器的实现,以及涉及到的相关对象
这两个处理器在哪被注册?
在前面的《解析自定义标签(XML 文件)》 和 《BeanDefinition 的解析过程(面向注解)》文章中可以知道,在 XML 文件中的
<context:component-scan />
标签的处理过程中,会底层借助于
ClassPathBeanDefinitionScanner
扫描器,去扫描指定路径下符合条件(@Component 注解)的 BeanDefinition 们,关于 @ComponentScan 注解的解析也是借助于这个扫描器实现的。扫描过程如下:
// ClassPathBeanDefinitionScanner.javapublic int scan(String... basePackages) {// <1> 获取扫描前的 BeanDefinition 数量int beanCountAtScanStart = this.registry.getBeanDefinitionCount();// <2> 进行扫描,将过滤出来的所有的 .class 文件生成对应的 BeanDefinition 并注册doScan(basePackages);// Register annotation config processors, if necessary.// <3> 如果 `includeAnnotationConfig` 为 `true`(默认),则注册几个关于注解的 PostProcessor 处理器(关键)// 在其他地方也会注册,内部会进行判断,已注册的处理器不会再注册if (this.includeAnnotationConfig) {AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}// <4> 返回本次扫描注册的 BeanDefinition 数量return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);}
在第
<3>
步会调用 AnnotationConfigUtils 的
registerAnnotationConfigProcessors(BeanDefinitionRegistry)
方法,如下:
// AnnotationConfigUtils.javapublic static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);}/*** Register all relevant annotation post processors in the given registry.* @param registry the registry to operate on* @param source the configuration source element (already extracted)* that this registration was triggered from. May be {@code null}.* @return a Set of BeanDefinitionHolders, containing all bean definitions* that have actually been registered by this call*/public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);// 处理 Spring 应用上下文中的配置类if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}// 处理 @Autowired 以及 @Value 注解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));}// (条件激活)处理 JSR-250 注解 @Resource,如 @PostConstruct、@PreDestroy 等// 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));}// Processor 对象(条件激活)处理 JPA 注解场景// 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));}// 处理标注 @EventListener 的 Spring 事件监听方法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));}// 用于 @EventListener 标注的事件监听方法构建成 ApplicationListener 对象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;}
在这个方法中可以看到会注册 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor 两个处理器,然后在 Spring 应用上下文刷新阶段会将其初始化并添加至 AbstractBeanFactory 的
beanPostProcessors
集合中,那么接下来我们先来分析这两个处理器
回顾 Bean 的创建过程
第一步:回到《Bean 的创建过程》文章中的“对 RootBeanDefinition 加工处理”小节,会调用这个方法:
// AbstractAutowireCapableBeanFactory.javaprotected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof MergedBeanDefinitionPostProcessor) {MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);}}}
调用所有 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法对 RootBeanDefinition 进行加工处理,例如:
- AutowiredAnnotationBeanPostProcessor,会先解析出
@Autowired
和
@Value
注解标注的属性的注入元信息,后续进行依赖注入
- CommonAnnotationBeanPostProcessor,会先解析出
@Resource
注解标注的属性的注入元信息,后续进行依赖注入,它也会找到
@PostConstruct
和
@PreDestroy
注解标注的方法,并构建一个 LifecycleMetadata 对象,用于后续生命周期中的初始化和销毁
第二步:回到《Bean 的创建过程》文章中的“属性填充”小节,该过程会进行下面的处理:
// <5> 通过 InstantiationAwareBeanPostProcessor 处理器(如果有)对 `pvs` 进行处理if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}// <5.1> 遍历所有的 BeanPostProcessorfor (BeanPostProcessor bp : getBeanPostProcessors()) {// 如果为 InstantiationAwareBeanPostProcessor 类型if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;// <5.2> 调用处理器的 `postProcessProperties(...)` 方法,对 `pvs` 进行后置处理PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);// <5.3> 如果上一步的处理结果为空,可能是新版本导致的(Spring 5.1 之前没有上面这个方法),则需要兼容老版本if (pvsToUse == null) {// <5.3.1> 找到这个 Bean 的所有 `java.beans.PropertyDescriptor` 属性描述器(包含这个属性的所有信息)if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}// <5.3.2> 调用处理器的 `postProcessPropertyValues(...)` 方法,对 `pvs` 进行后置处理pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);// <5.3.3> 如果处理后的 PropertyValues 对象为空,直接 `return`,则不会调用后面的 InstantiationAwareBeanPostProcessor 处理器,也不会进行接下来的属性填充if (pvsToUse == null) {return;}}// <5.4> 将处理后的 `pvsToUse` 复制给 `pvs`pvs = pvsToUse;}}}
这里不会调用所有 InstantiationAwareBeanPostProcessor 的 postProcessProperties 方法对
pvs
(MutablePropertyValues)属性值对象进行处理,例如:
- AutowiredAnnotationBeanPostProcessor,会根据前面解析出来的
@Autowired
和
@Value
注解标注的属性的注入元信息,进行依赖注入
- CommonAnnotationBeanPostProcessor,会根据前面解析出来的
@Resource
注解标注的属性的注入元信息,进行依赖注入
可以看到
@Autowired
、
@Value
和
@Resource
注解的实现就是基于这两个处理器实现的,接下来我们来看看这两个处理器的具体实现
AutowiredAnnotationBeanPostProcessor
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
,主要处理
@Autowired
和
@Value
注解进行依赖注入
体系结构
可以看到 AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor 和 InstantiationAwareBeanPostProcessor 两个接口
构造方法
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapterimplements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {/*** 保存需要处理的注解*/private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);private String requiredParameterName = "required";private boolean requiredParameterValue = true;private int order = Ordered.LOWEST_PRECEDENCE - 2;@Nullableprivate ConfigurableListableBeanFactory beanFactory;private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);/*** 缓存需要注入的字段元信息*/private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);/*** Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring\'s* standard {@link Autowired @Autowired} annotation.* <p>Also supports JSR-330\'s {@link javax.inject.Inject @Inject} annotation,* if available.*/@SuppressWarnings("unchecked")public AutowiredAnnotationBeanPostProcessor() {this.autowiredAnnotationTypes.add(Autowired.class);this.autowiredAnnotationTypes.add(Value.class);try {this.autowiredAnnotationTypes.add((Class<? extends Annotation>)ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));logger.trace("JSR-330 \'javax.inject.Inject\' annotation found and supported for autowiring");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}}
可以看到会添加
@Autowired
和
@Value
两个注解,如果存在 JSR-330 的
javax.inject.Inject
注解,也是支持的
postProcessMergedBeanDefinition 方法
postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
方法,找到
@Autowired
和
@Value
注解标注的字段(或方法)的元信息,如下:
@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {// 找到这个 Bean 所有需要注入的属性(@Autowired 或者 @Value 注解)InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}
直接调用
findAutowiringMetadata(...)
方法获取这个 Bean 的注入元信息对象
1. findAutowiringMetadata 方法
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {// Fall back to class name as cache key, for backwards compatibility with custom callers.// 生成一个缓存 KeyString cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());// Quick check on the concurrent map first, with minimal locking.// 先尝试从缓存中获取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);}// 构建一个需要注入的元信息对象metadata = buildAutowiringMetadata(clazz);this.injectionMetadataCache.put(cacheKey, metadata);}}}return metadata;}
首先尝试从缓存中获取这个 Bean 对应的注入元信息对象,没有找到的话则调用
buildAutowiringMetadata(final Class<?> clazz)
构建一个,然后再放入缓存中
2. buildAutowiringMetadata 方法
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {// <1> 创建 `currElements` 集合,用于保存 @Autowired、@Value 注解标注的字段final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();// <2> 遍历这个 Class 对象的所有字段ReflectionUtils.doWithLocalFields(targetClass, field -> {// <2.1> 找到该字段的 @Autowired 或者 @Value 注解,返回 `ann` 对象,没有的话返回空对象,则直接跳过不进行下面的操作AnnotationAttributes ann = findAutowiredAnnotation(field);if (ann != null) {// <2.2> 进行过滤,static 修饰的字段不进行注入if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static fields: " + field);}return;}// <2.3> 获取注解中的 `required` 配置boolean required = determineRequiredStatus(ann);// <2.4> 根据该字段和 `required` 构建一个 AutowiredFieldElement 对象,添加至 `currElements`currElements.add(new AutowiredFieldElement(field, required));}});// <3> 遍历这个 Class 对象的所有方法ReflectionUtils.doWithLocalMethods(targetClass, method -> {// <3.1> 尝试找到这个方法的桥接方法,没有的话就是本身这个方法Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);// <3.2> 如果是桥接方法则直接跳过if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;}// <3.3> 找到该方法的 @Autowired 或者 @Value 注解,返回 `ann` 对象,没有的话返回空对象,则直接跳过不进行下面的操作AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {// <3.4> 进行过滤,static 修饰的方法不进行注入if (Modifier.isStatic(method.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static methods: " + method);}return;}if (method.getParameterCount() == 0) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation should only be used on methods with parameters: " +method);}}// <3.5> 获取注解中的 `required` 配置boolean required = determineRequiredStatus(ann);PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);// <3.6> 构建一个 AutowiredMethodElement 对象,添加至 `currElements`currElements.add(new AutowiredMethodElement(method, required, pd));}});elements.addAll(0, currElements);// <4> 找到父类,循环遍历targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);// <5> 根据从这个 Bean 解析出来的所有 InjectedElement 对象生成一个 InjectionMetadata 注入元信息对象,并返回return new InjectionMetadata(clazz, elements);}
过程如下:
- 创建
currElements
集合,用于保存
@Autowired
、
@Value
注解标注的字段
- 遍历这个 Class 对象的所有字段找到该字段的
@Autowired
或者
@Value
注解,返回
ann
对象,没有的话返回空对象,则直接跳过不进行下面的操作
- 进行过滤,static 修饰的字段不进行注入
- 获取注解中的
required
配置
- 根据该字段和
required
构建一个 AutowiredFieldElement 对象,添加至
currElements
- 尝试找到这个方法的桥接方法,没有的话就是本身这个方法
@Autowired
或者
@Value
注解,返回
ann
对象,没有的话返回空对象,则直接跳过不进行下面的操作
required
配置
currElements
整个过程很简单,就是解析出所有
@Autowired
或者
@Value
注解标注的方法或者字段,然后构建一个 InjectionMetadata 注入元信息对象
postProcessProperties 方法
postProcessProperties(PropertyValues pvs, Object bean, String beanName)
方法,根据
@Autowired
和
@Value
注解标注的字段(或方法)的元信息进行依赖注入,如下:
@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {// 找到这个 Bean 的注入元信息对象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;}
先找到这个 Bean 的注入元信息对象,上面已经讲过了,然后调用其
inject(...)
方法,这里先来看到
InjectionMetadata
这个对象
InjectionMetadata 注入元信息对象
org.springframework.beans.factory.annotation.InjectionMetadata
,某个 Bean 的注入元信息对象
public class InjectionMetadata {private static final Log logger = LogFactory.getLog(InjectionMetadata.class);private final Class<?> targetClass;/*** 需要注入的字段(或方法)的元信息*/private final Collection<InjectedElement> injectedElements;@Nullableprivate volatile Set<InjectedElement> checkedElements;public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {this.targetClass = targetClass;this.injectedElements = elements;}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) {if (logger.isTraceEnabled()) {logger.trace("Processing injected element of bean \'" + beanName + "\': " + element);}element.inject(target, beanName, pvs);}}}}
可以看到注入方法非常简单,就是遍历所有的 InjectedElement 对象,调用他们的
inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)
方法
AutowiredFieldElement
AutowiredAnnotationBeanPostProcessor 的私有内部类,注入字段对象,如下:
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {/** 是否必须 */private final boolean required;/** 是否缓存起来了 */private volatile boolean cached = false;/** 缓存的对象 */@Nullableprivate volatile Object cachedFieldValue;public AutowiredFieldElement(Field field, boolean required) {super(field, null);this.required = required;}@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {// <1> 获取 `field` 字段Field field = (Field) this.member;Object value;// <2> 如果进行缓存了,则尝试从缓存中获取if (this.cached) {value = resolvedCachedArgument(beanName, this.cachedFieldValue);}// <3> 否则,开始进行解析else {// <3.1> 创建一个依赖注入描述器 `desc`DependencyDescriptor desc = new DependencyDescriptor(field, this.required);desc.setContainingClass(bean.getClass());Set<String> autowiredBeanNames = new LinkedHashSet<>(1);Assert.state(beanFactory != null, "No BeanFactory available");TypeConverter typeConverter = beanFactory.getTypeConverter();try {/*** <3.2> 通过 {@link org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency} 方法* 找到这个字段对应的 Bean(们)*/value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);}// <3.3> 和缓存相关,如果有必要则将本次找到的注入对象缓存起来,避免下次再进行解析synchronized (this) {if (!this.cached) {if (value != null || this.required) {this.cachedFieldValue = desc;registerDependentBeans(beanName, autowiredBeanNames);if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());}}}else {this.cachedFieldValue = null;}this.cached = true;}}}// <4> 如果获取到该字段对应的对象,则进行属性赋值(依赖注入)if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);}}}
直接看到
inject(...)
方法,注入的过程如下:
- 获取
field
字段
- 如果进行缓存了,则尝试从缓存中获取
- 否则,开始进行解析创建一个依赖注入描述器
desc
- **【核心】**通过
DefaultListableBeanFactory#resolveDependency(...)
方法,找到这个字段对应的 Bean(们)
- 和缓存相关,如果有必要则将本次找到的注入对象缓存起来,避免下次再进行解析
可以看到整个的核心在于通过
DefaultListableBeanFactory#resolveDependency(...)
方法找到字段对应的 Bean,这里也许是一个集合对象,所以也可能找到的是多个 Bean,该方法在后面进行分析
AutowiredMethodElement
AutowiredAnnotationBeanPostProcessor 的私有内部类,注入方法对象,如下:
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {/** 是否必须 */private final boolean required;/** 是否缓存起来了 */private volatile boolean cached = false;/** 缓存的方法参数对象 */@Nullableprivate volatile Object[] cachedMethodArguments;public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {super(method, pd);this.required = required;}@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {if (checkPropertySkipping(pvs)) {return;}// <1> 获取 `method` 方法Method method = (Method) this.member;// <2> 如果进行缓存了,则尝试从缓存中获取方法参数对象Object[] arguments;if (this.cached) {// Shortcut for avoiding synchronization...arguments = resolveCachedArguments(beanName);}// <3> 否则,开始进行解析else {// <3.1> 获取方法的参数类型集合 `paramTypes`,根据参数位置确定参数Class<?>[] paramTypes = method.getParameterTypes();arguments = new Object[paramTypes.length];// <3.2> 构建一个依赖注入描述器数组 `descriptors`,用于保存后续创建的对象DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);Assert.state(beanFactory != null, "No BeanFactory available");TypeConverter typeConverter = beanFactory.getTypeConverter();// <3.3> 根据参数顺序遍历该方法的参数for (int i = 0; i < arguments.length; i++) {// <3.3.1> 为第 `i` 个方法参数创建一个 MethodParameter 对象MethodParameter methodParam = new MethodParameter(method, i);// <3.3.2> 创建依赖描述器 `currDesc`,并添加至 `descriptors` 数组DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);currDesc.setContainingClass(bean.getClass());descriptors[i] = currDesc;try {/*** <3.3.3> 通过 {@link org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency} 方法* 找到这个方法参数对应的 Bean(们)*/Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);if (arg == null && !this.required) {arguments = null;break;}arguments[i] = arg;}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);}}// <3.4> 和缓存相关,如果有必要则将本次找到的方法参数对象缓存起来,避免下次再进行解析synchronized (this) {if (!this.cached) {if (arguments != null) {Object[] cachedMethodArguments = new Object[paramTypes.length];System.arraycopy(descriptors, 0, cachedMethodArguments, 0, arguments.length);registerDependentBeans(beanName, autowiredBeans);if (autowiredBeans.size() == paramTypes.length) {Iterator<String> it = autowiredBeans.iterator();for (int i = 0; i < paramTypes.length; i++) {String autowiredBeanName = it.next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName, paramTypes[i]);}}}this.cachedMethodArguments = cachedMethodArguments;}else {this.cachedMethodArguments = null;}this.cached = true;}}}// <4> 如果找到该方法的参数(们),则进行属性赋值(依赖注入)if (arguments != null) {try {ReflectionUtils.makeAccessible(method);// 通过反射机制调用该方法method.invoke(bean, arguments);}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}}
直接看到
inject(...)
方法,注入的过程如下:
- 获取
method
方法
- 如果进行缓存了,则尝试从缓存中获取方法参数对象
- 否则,开始进行解析获取方法的参数类型集合
paramTypes
,根据参数位置确定参数
- 构建一个依赖注入描述器数组
descriptors
,用于保存后续创建的对象
- 根据参数顺序遍历该方法的参数为第
i
个方法参数创建一个 MethodParameter 对象
- 创建依赖描述器
currDesc
,并添加至
descriptors
数组
- **【核心】**通过
DefaultListableBeanFactory#resolveDependency(...)
方法,找到这个方法参数对应的 Bean(们)
- 和缓存相关,如果有必要则将本次找到的方法参数对象缓存起来,避免下次再进行解析
可以看到整个的核心也是通过
DefaultListableBeanFactory#resolveDependency(...)
方法找到方法参数对应的 Bean,该方法在后面进行分析
CommonAnnotationBeanPostProcessor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
,主要处理
@Resource
注解进行依赖注入,以及
@PostConstruct
和
@PreDestroy
生命周期注解的处理
体系结构
可以看到 CommonAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor 和 InstantiationAwareBeanPostProcessor 两个接口,还实现了 DestructionAwareBeanPostProcessor 接口,用于生命周期中的初始化和销毁的处理
构造方法
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessorimplements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {@Nullableprivate static Class<? extends Annotation> webServiceRefClass;@Nullableprivate static Class<? extends Annotation> ejbRefClass;static {try {@SuppressWarnings("unchecked")Class<? extends Annotation> clazz = (Class<? extends Annotation>)ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());webServiceRefClass = clazz;}catch (ClassNotFoundException ex) {webServiceRefClass = null;}try {@SuppressWarnings("unchecked")Class<? extends Annotation> clazz = (Class<? extends Annotation>)ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());ejbRefClass = clazz;}catch (ClassNotFoundException ex) {ejbRefClass = null;}}/*** Create a new CommonAnnotationBeanPostProcessor,* with the init and destroy annotation types set to* {@link javax.annotation.PostConstruct} and {@link javax.annotation.PreDestroy},* respectively.*/public CommonAnnotationBeanPostProcessor() {setOrder(Ordered.LOWEST_PRECEDENCE - 3);setInitAnnotationType(PostConstruct.class);setDestroyAnnotationType(PreDestroy.class);ignoreResourceType("javax.xml.ws.WebServiceContext");}}public class InitDestroyAnnotationBeanPostProcessorimplements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {protected transient Log logger = LogFactory.getLog(getClass());/*** 初始化注解,默认为 @PostConstruct*/@Nullableprivate Class<? extends Annotation> initAnnotationType;/*** 销毁注解,默认为 @PreDestroy*/@Nullableprivate Class<? extends Annotation> destroyAnnotationType;private int order = Ordered.LOWEST_PRECEDENCE;@Nullableprivate final transient Map<Class<?>, LifecycleMetadata> lifecycleMetadataCache = new ConcurrentHashMap<>(256);public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {this.initAnnotationType = initAnnotationType;}public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {this.destroyAnnotationType = destroyAnnotationType;}}
可以看到会设置初始化注解为
@PostConstruct
,销毁注解为
@PreDestroy
,这两个注解都是 JSR-250 注解;另外如果存在
javax.xml.ws.WebServiceRef
和
javax.ejb.EJB
注解也是会进行设置的
postProcessMergedBeanDefinition 方法
postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
方法,找到
@PostConstruct
和
@PreDestroy
注解标注的方法,并构建 LifecycleMetadata 对象,找到
@Resource
注解标注的字段(或方法)的元信息,如下:
// CommonAnnotationBeanPostProcessor.java@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {// 先调用父类的方法,找到 @PostConstruct 和 @PreDestroy 注解标注的方法,并构建 LifecycleMetadata 对象super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);// 找到 @Resource 注解标注的字段(或方法),构建一个 InjectionMetadata 对象,用于后续的属性注入InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}
整个的过程原理和 AutowiredAnnotationBeanPostProcessor 差不多,先从缓存中获取,未命中则调用对应的方法进行构建,下面先来看看父类中的方法
buildLifecycleMetadata 方法
// InitDestroyAnnotationBeanPostProcessor.javaprivate LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {List<LifecycleElement> initMethods = new ArrayList<>();List<LifecycleElement> destroyMethods = new ArrayList<>();Class<?> targetClass = clazz;do {final List<LifecycleElement> currInitMethods = new ArrayList<>();final List<LifecycleElement> currDestroyMethods = new ArrayList<>();ReflectionUtils.doWithLocalMethods(targetClass, method -> {if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {LifecycleElement element = new LifecycleElement(method);currInitMethods.add(element);if (logger.isTraceEnabled()) {logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);}}if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {currDestroyMethods.add(new LifecycleElement(method));if (logger.isTraceEnabled()) {logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);}}});initMethods.addAll(0, currInitMethods);destroyMethods.addAll(currDestroyMethods);targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return new LifecycleMetadata(clazz, initMethods, destroyMethods);}
整个过程比较简单,找到这个 Bean 中
@PostConstruct
和
@PreDestroy
注解标注的方法,然后构建一个 LifecycleMetadata 生命周期元信息对象
buildResourceMetadata 方法
// CommonAnnotationBeanPostProcessor.javaprivate InjectionMetadata buildResourceMetadata(final Class<?> clazz) {List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();ReflectionUtils.doWithLocalFields(targetClass, field -> {if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");}currElements.add(new WebServiceRefElement(field, field, null));}else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@EJB annotation is not supported on static fields");}currElements.add(new EjbRefElement(field, field, null));}else if (field.isAnnotationPresent(Resource.class)) {if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@Resource annotation is not supported on static fields");}if (!this.ignoredResourceTypes.contains(field.getType().getName())) {currElements.add(new ResourceElement(field, field, null));}}});ReflectionUtils.doWithLocalMethods(targetClass, method -> {Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;}if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {if (Modifier.isStatic(method.getModifiers())) {throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");}if (method.getParameterCount() != 1) {throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);}PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));}else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {if (Modifier.isStatic(method.getModifiers())) {throw new IllegalStateException("@EJB annotation is not supported on static methods");}if (method.getParameterCount() != 1) {throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);}PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new EjbRefElement(method, bridgedMethod, pd));}else if (bridgedMethod.isAnnotationPresent(Resource.class)) {if (Modifier.isStatic(method.getModifiers())) {throw new IllegalStateException("@Resource annotation is not supported on static methods");}Class<?>[] paramTypes = method.getParameterTypes();if (paramTypes.length != 1) {throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);}if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new ResourceElement(method, bridgedMethod, pd));}}}});elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return new InjectionMetadata(clazz, elements);}
整个过程也比较简单,解析出这个 Bean 带有
@Resource
注解的所有字段(或方法),构建成对应的 ResourceElement 对象,然后再构建成一个 InjectionMetadata 注入元信息对象
postProcessProperties 方法
postProcessProperties(PropertyValues pvs, Object bean, String beanName)
方法,根据
@Resource
注解标注的字段(或方法)的元信息进行依赖注入,如下:
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);try {// 进行注入metadata.inject(bean, beanName, pvs);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);}return pvs;}
先找到这个 Bean 的注入元信息对象,上面已经讲过了,然后调用其
inject(...)
方法,该对象上面已经讲过了,实际就是调用其内部 InjectedElement 的
inject(...)
方法
postProcessBeforeInitialization 方法
初始化 Bean 的时候会先执行
@PostConstruct
标注的初始化方法
// InitDestroyAnnotationBeanPostProcessor.java@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 找到 @PostConstruct 和 @PreDestroy 注解标注的方法们所对应的 LifecycleMetadata 对象LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());try {// 执行 @PostConstruct 标注的初始化方法metadata.invokeInitMethods(bean, beanName);}catch (InvocationTargetException ex) {throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());}catch (Throwable ex) {throw new BeanCreationException(beanName, "Failed to invoke init method", ex);}return bean;}// InitDestroyAnnotationBeanPostProcessor.LifecycleMetadatapublic void invokeInitMethods(Object target, String beanName) throws Throwable {Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;Collection<LifecycleElement> initMethodsToIterate =(checkedInitMethods != null ? checkedInitMethods : this.initMethods);if (!initMethodsToIterate.isEmpty()) {for (LifecycleElement element : initMethodsToIterate) {if (logger.isTraceEnabled()) {logger.trace("Invoking init method on bean \'" + beanName + "\': " + element.getMethod());}element.invoke(target);}}}
postProcessBeforeDestruction 方法
销毁 Bean 的时候先执行
@PreDestroy
注解标注的销毁方法
// InitDestroyAnnotationBeanPostProcessor.java@Overridepublic void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {// 找到 @PostConstruct 和 @PreDestroy 注解标注的方法们所对应的 LifecycleMetadata 对象LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());try {// 执行 @PreDestroy 标注的销毁方法metadata.invokeDestroyMethods(bean, beanName);}catch (InvocationTargetException ex) {String msg = "Destroy method on bean with name \'" + beanName + "\' threw an exception";if (logger.isDebugEnabled()) {logger.warn(msg, ex.getTargetException());}else {logger.warn(msg + ": " + ex.getTargetException());}}catch (Throwable ex) {logger.warn("Failed to invoke destroy method on bean with name \'" + beanName + "\'", ex);}}// InitDestroyAnnotationBeanPostProcessor.LifecycleMetadatapublic void invokeDestroyMethods(Object target, String beanName) throws Throwable {Collection<LifecycleElement> checkedDestroyMethods = this.checkedDestroyMethods;Collection<LifecycleElement> destroyMethodsToUse =(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);if (!destroyMethodsToUse.isEmpty()) {for (LifecycleElement element : destroyMethodsToUse) {if (logger.isTraceEnabled()) {logger.trace("Invoking destroy method on bean \'" + beanName + "\': " + element.getMethod());}element.invoke(target);}}}
ResourceElement
CommonAnnotationBeanPostProcessor 的私有内部类,@Resource 注入字段(或方法)对象
构造方法
protected abstract class LookupElement extends InjectionMetadata.InjectedElement {/** Bean 的名称 */protected String name = "";/** 是否为默认的名称(通过注解定义的) */protected boolean isDefaultName = false;/** Bean 的类型 */protected Class<?> lookupType = Object.class;@Nullableprotected String mappedName;public LookupElement(Member member, @Nullable PropertyDescriptor pd) {super(member, pd);}public final DependencyDescriptor getDependencyDescriptor() {if (this.isField) {return new LookupDependencyDescriptor((Field) this.member, this.lookupType);}else {return new LookupDependencyDescriptor((Method) this.member, this.lookupType);}}}private class ResourceElement extends LookupElement {/** 是否延迟加载 */private final boolean lazyLookup;public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {super(member, pd);Resource resource = ae.getAnnotation(Resource.class);String resourceName = resource.name();Class<?> resourceType = resource.type();this.isDefaultName = !StringUtils.hasLength(resourceName);if (this.isDefaultName) {resourceName = this.member.getName();if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {resourceName = Introspector.decapitalize(resourceName.substring(3));}}else if (embeddedValueResolver != null) {resourceName = embeddedValueResolver.resolveStringValue(resourceName);}if (Object.class != resourceType) {checkResourceType(resourceType);}else {// No resource type specified... check field/method.resourceType = getResourceType();}this.name = (resourceName != null ? resourceName : "");this.lookupType = resourceType;String lookupValue = resource.lookup();this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());Lazy lazy = ae.getAnnotation(Lazy.class);this.lazyLookup = (lazy != null && lazy.value());}}
ResourceElement 的构造方法会通过
@Resource
注解和该字段(或方法)解析出基本信息
可以看到还继承了 InjectionMetadata 的静态内部类 InjectedElement,我们先来看到这个类的
inject(...)
方法
inject 方法
public abstract static class InjectedElement {protected final Member member;protected final boolean isField;protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)throws Throwable {if (this.isField) {Field field = (Field) this.member;ReflectionUtils.makeAccessible(field);field.set(target, getResourceToInject(target, requestingBeanName));} else {if (checkPropertySkipping(pvs)) {return;}try {Method method = (Method) this.member;ReflectionUtils.makeAccessible(method);method.invoke(target, getResourceToInject(target, requestingBeanName));}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}@Nullableprotected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {return null;}}
不管是字段还是方法,底层都是通过反射机制进行赋值或者调用,都会调用
getResourceToInject(...)
方法获取到字段值或者方法参数
getResourceToInject 方法
@Overrideprotected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :getResource(this, requestingBeanName));}
如果是延迟加载,则调用
buildLazyResourceProxy(...)
方法返回一个代理对象,如下:
protected Object buildLazyResourceProxy(final LookupElement element, final @Nullable String requestingBeanName) {TargetSource ts = new TargetSource() {@Overridepublic Class<?> getTargetClass() {return element.lookupType;}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() {return getResource(element, requestingBeanName);}@Overridepublic void releaseTarget(Object target) {}};ProxyFactory pf = new ProxyFactory();pf.setTargetSource(ts);if (element.lookupType.isInterface()) {pf.addInterface(element.lookupType);}ClassLoader classLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : null);return pf.getProxy(classLoader);}
否则,调用
getResource(...)
方法获取注入对象
getResource 方法
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)throws NoSuchBeanDefinitionException {if (StringUtils.hasLength(element.mappedName)) {return this.jndiFactory.getBean(element.mappedName, element.lookupType);}if (this.alwaysUseJndiLookup) {return this.jndiFactory.getBean(element.name, element.lookupType);}if (this.resourceFactory == null) {throw new NoSuchBeanDefinitionException(element.lookupType,"No resource factory configured - specify the \'resourceFactory\' property");}return autowireResource(this.resourceFactory, element, requestingBeanName);}
前面的判断忽略掉,直接看到最后会调用
autowireResource(...)
方法,并返回注入信息
autowireResource 方法
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)throws NoSuchBeanDefinitionException {Object resource;Set<String> autowiredBeanNames;String name = element.name;if (factory instanceof AutowireCapableBeanFactory) {AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;DependencyDescriptor descriptor = element.getDependencyDescriptor();if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {autowiredBeanNames = new LinkedHashSet<>();resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);if (resource == null) {throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");}}else {resource = beanFactory.resolveBeanByName(name, descriptor);autowiredBeanNames = Collections.singleton(name);}}else {resource = factory.getBean(name, element.lookupType);autowiredBeanNames = Collections.singleton(name);}if (factory instanceof ConfigurableBeanFactory) {ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;for (String autowiredBeanName : autowiredBeanNames) {if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);}}}return resource;}
@Resource
注解相比于
@Autowired
注解的处理更加复杂点,不过我们这里可以看到也会调用
DefaultListableBeanFactory#resolveDependency(...)
方法,找到对应的注入对象,该方法在后面进行分析
1. resolveDependency 处理依赖方法
resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set<String> autowiredBeanNames, TypeConverter typeConverter)
方法,找到对应的依赖 Bean,该方法在《Bean 的创建过程》中也提到了,获取 Bean 的实例对象时,构造器注入的参数也是通过该方法获取的,本文的依赖注入底层也是通过该方法实现的,这里我们对该方法一探究竟
// DefaultListableBeanFactory.java@Override@Nullablepublic Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {// <1> 设置参数名称探测器,例如通过它获取方法参数的名称descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());// <2> 如果依赖类型为 Optional 类型if (Optional.class == descriptor.getDependencyType()) {// 调用 `createOptionalDependency(...)` 方法,先将 `descriptor` 注入表述器封装成 NestedDependencyDescriptor 对象// 底层处理和下面的 `5.2` 相同return createOptionalDependency(descriptor, requestingBeanName);}// <3> 否则,如果依赖类型为 ObjectFactory 或 ObjectProvider 类型else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) {// 返回一个 DependencyObjectProvider 私有内部类对象,并没有获取到实例的 Bean,需要调用其 getObject() 方法获取目标对象return new DependencyObjectProvider(descriptor, requestingBeanName);}// <4> 否则,如果依赖类型为 javax.inject.Provider 类型else if (javaxInjectProviderClass == descriptor.getDependencyType()) {// 返回一个 Jsr330Provider 私有内部类对象,该对象也继承 DependencyObjectProviderreturn new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}// <5> 否则,通用的处理逻辑else {// <5.1> 先通过 AutowireCandidateResolver 尝试获取一个代理对象,延迟依赖注入则会返回一个代理对象Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);// <5.2> 如果上面没有返回代理对象,则进行处理,调用 `doResolveDependency(...)` 方法if (result == null) {result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}
过程如下:
- 设置参数名称探测器,例如通过它获取方法参数的名称
- 如果依赖类型为 Optional 类型,则调用
createOptionalDependency(...)
方法,先将
descriptor
注入表述器封装成 NestedDependencyDescriptor 对象,底层处理和下面的
5.2
相同
- 否则,如果依赖类型为 ObjectFactory 或 ObjectProvider 类型,直接返回一个
DependencyObjectProvider
私有内部类对象,并没有获取到实例的 Bean,需要调用其 getObject() 方法获取目标对象
- 否则,如果依赖类型为 javax.inject.Provider 类型,直接返回一个
Jsr330Provider
私有内部类对象,该对象也继承 DependencyObjectProvider
- 否则,通用的处理逻辑先通过 AutowireCandidateResolver 尝试获取一个代理对象,延迟依赖注入则会返回一个代理对象
- 如果上面没有返回代理对象,则进行处理,调用
doResolveDependency(...)
方法
我们需要关注的是上面的第
5.2
步所调用
doResolveDependency(...)
方法,这一步是底层实现
2. doResolveDependency 底层处理依赖方法
// DefaultListableBeanFactory.java@Nullablepublic Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {// 设置当前线程的注入点,并返回上次的注入点,属于嵌套注入的一个保护点InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);try {// <1> 针对给定的工厂给定一个快捷实现的方式,暂时忽略// 例如考虑一些预先解析的信息,在进入所有 Bean 的常规类型匹配算法之前,解析算法将首先尝试通过此方法解析快捷方式Object shortcut = descriptor.resolveShortcut(this);if (shortcut != null) {// 返回快捷的解析信息return shortcut;}// 依赖的类型Class<?> type = descriptor.getDependencyType();// <2> 获取注解中的 value 对应的值,例如 @Value、@Qualifier 注解配置的 value 属性值,注意 @Autowired 没有 value 属性配置Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);if (value != null) {if (value instanceof String) {// <2.1> 解析注解中的 value,因为可能是占位符,需要获取到相应的数据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 {// <2.2> 进行类型转换,并返回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()));}}// <3> 解析复合的依赖对象(Array、Collection、Map 类型),获取该属性元素类型的 Bean 们// 底层和第 `4` 原理一样,这里会将 `descriptor` 封装成 MultiElementDescriptor 类型Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;}// <4> 查找与类型相匹配的 Bean 们// 返回结果:key -> beanName;value -> 对应的 BeanMap<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);// <5> 如果一个都没找到if (matchingBeans.isEmpty()) {// <5.1> 如果 @Autowired 配置的 required 为 true,表示必须,则抛出异常if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}// <5.2> 否则,返回一个空对象return null;}String autowiredBeanName;Object instanceCandidate;// <6> 如果匹配的 Bean 有多个,则需要找出最优先的那个if (matchingBeans.size() > 1) {// <6.1> 找到最匹配的那个 Bean,通过 @Primary 或者 @Priority 来决定,或者通过名称决定autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName == null) {if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {// <6.2> 如果没有找到最匹配的 Bean,则抛出 NoUniqueBeanDefinitionException 异常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;}}// <6.3> 获取到最匹配的 Bean,传值引用给 `instanceCandidate`instanceCandidate = matchingBeans.get(autowiredBeanName);}// <7> 否则,只有一个 Bean,则直接使用其作为最匹配的 Beanelse {// We have exactly one match.Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();autowiredBeanName = entry.getKey();instanceCandidate = entry.getValue();}// <8> 将依赖注入的 Bean 的名称添加至方法入参 `autowiredBeanNames` 集合,里面保存依赖注入的 beanNameif (autowiredBeanNames != null) {autowiredBeanNames.add(autowiredBeanName);}// <9> 如果匹配的 Bean 是 Class 对象,则根据其 beanName 依赖查找到对应的 Beanif (instanceCandidate instanceof Class) {instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;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());}// <10> 返回依赖注入的 Beanreturn result;}finally {// 设置当前线程的注入点为上一次的注入点,因为本次注入结束了ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);}}
依赖处理的过程稍微有点复杂,如下:
-
针对给定的工厂给定一个快捷实现的方式,暂时忽略
例如考虑一些预先解析的信息,在进入所有 Bean 的常规类型匹配算法之前,解析算法将首先尝试通过此方法解析快捷方式
-
获取注解中的 value 对应的值,例如
@Value
、
@Qualifier
注解配置的 value 属性值,注意 @Autowired 没有 value 属性配置
解析注解中的 value,因为可能是占位符,需要获取到相应的数据
- 进行类型转换,并返回
解析复合的依赖对象(Array、Collection、Map 类型),获取该属性元素类型的 Bean 们,调用
resolveMultipleBeans(...)
方法
底层和下面第
4
步原理一样,这里会将
descriptor
封装成 MultiElementDescriptor 类型,如果找到了则直接返回
查找与类型相匹配的 Bean 们,调用
findAutowireCandidates(...)
方法
返回结果:key -> beanName;value -> 对应的 Bean
如果一个都没找到
- 如果
@Autowired
配置的 required 为 true,表示必须,则抛出异常
如果匹配的 Bean 有多个,则需要找出最优先的那个
- 找到最匹配的那个 Bean,通过
@Primary
或者
@Priority
来决定,或者通过名称决定,调用
determineAutowireCandidate(...)
方法
instanceCandidate
否则,只有一个 Bean,则直接使用其作为最匹配的 Bean
将依赖注入的 Bean 的名称添加至方法入参
autowiredBeanNames
集合,里面保存依赖注入的 beanName
如果匹配的 Bean 是 Class 对象,则根据其 beanName 依赖查找到对应的 Bean
返回依赖注入的 Bean
关于上面第
3
步对于符合依赖对象的处理这里不做详细分析,因为底层和第
4
步一样,接下来分析上面第
4
、
6
步所调用的方法
findAutowireCandidates 方法
findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor)
方法,找到符合条件的依赖注入的 Bean 们,如下:
// DefaultListableBeanFactory.javaprotected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {// <1> 从当前上下文找到该类型的 Bean 们(根据类型)String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());// <2> 定义一个 Map 对象 `result`,用于保存符合条件的 BeanMap<String, Object> result = new LinkedHashMap<>(candidateNames.length);/*** <3> 遍历 Spring 内部已处理的依赖对象集合,可以跳到 AbstractApplicationContext#prepareBeanFactory 方法中看看* 会有一下几个内置处理对象:* BeanFactory 类型 -> 返回 DefaultListableBeanFactory* ResourceLoader、ApplicationEventPublisher、ApplicationContext 类型 -> 返回 ApplicationContext 对象*/for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {Class<?> autowiringType = classObjectEntry.getKey();if (autowiringType.isAssignableFrom(requiredType)) {Object autowiringValue = classObjectEntry.getValue();autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);if (requiredType.isInstance(autowiringValue)) {result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);break;}}}// <4> 遍历第 `1` 步找到的 Bean 的名称们for (String candidate : candidateNames) {// <4.1> 如果满足下面两个条件,则添加至 `result` 集合中if (!isSelfReference(beanName, candidate) // 如果不是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)&& isAutowireCandidate(candidate, descriptor)) { // 符合注入的条件addCandidateEntry(result, candidate, descriptor, requiredType);}}// <5> 如果没有找到符合条件的 Bean,则再尝试获取if (result.isEmpty()) {boolean multiple = indicatesMultipleBeans(requiredType);// Consider fallback matches if the first pass failed to find anything...DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();// <5.1> 再次遍历第 `1` 步找到的 Bean 的名称们for (String candidate : candidateNames) {// <5.2> 如果满足下面三个条件,则添加至 `result` 集合中if (!isSelfReference(beanName, candidate) // 如果不是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)&& isAutowireCandidate(candidate, fallbackDescriptor) // 符合注入的条件&& (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) { // 不是复合类型,或者有 @Qualifier 注解addCandidateEntry(result, candidate, descriptor, requiredType);}}// <6> 如果还没有找到符合条件的 Bean,则再尝试获取// 和上面第 `5` 步的区别在于必须是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)if (result.isEmpty() && !multiple) {// Consider self references as a final pass...// but in the case of a dependency collection, not the very same bean itself.for (String candidate : candidateNames) {if (isSelfReference(beanName, candidate)&& (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate))&& isAutowireCandidate(candidate, fallbackDescriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}}}// <7> 返回 `result`,符合条件的 Beanreturn result;}
过程大致如下:
-
从当前上下文找到该类型的 Bean 们(根据类型)
-
定义一个 Map 对象
result
,用于保存符合条件的 Bean
-
遍历 Spring 内部已处理的依赖对象集合,例如你依赖注入 BeanFactory 类型的对象,则拿到的是 DefaultListableBeanFactory 对象,依赖注入 ResourceLoader、ApplicationEventPublisher、ApplicationContext 类型的对象, 拿到的就是当前 Spring 上下文 ApplicationContext 对象
-
遍历第
1
步找到的 Bean 的名称们
如果满足下面两个条件,则添加至
result
集合中
如果不是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)、符合注入的条件
如果没有找到符合条件的 Bean,则再尝试获取
再次遍历第
1
步找到的 Bean 的名称们
如果满足下面三个条件,则添加至
result
集合中
如果不是自引用(这个 Bean 不是在需要依赖它的 Bean 的内部定义的)、符合注入的条件、不是复合类型,或者有
@Qualifier
注解
如果还没有找到符合条件的 Bean,则再尝试获取,和上面第
5
步的区别在于必须是自引用(这个 Bean 是在需要依赖它的 Bean 的内部定义的)
返回
result
,符合条件的 Bean
总结下来:从当前上下文找到所有该类型的依赖注入对象然后返回,注意,如果你依赖注入的对象就是本身这个 Bean 内部定义的对象有特殊处理。
例如注入一个集合对象,元素类型的 Bean 有一个是定义在本身这个 Bean 的内部,如果仅有这个 Bean 则会注入进行;如果除了本身这个 Bean 内部定义了,其他地方也定义了,那么本身这个 Bean 内部定义的 Bean 是不会被注入的;因为是自引用的 Bean 不会优先考虑,除非一个都没找到,才会尝试获取自引用的 Bean
determineAutowireCandidate 方法
determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor)
方法,找到最匹配的那个依赖注入对象,如下:
@Nullableprotected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {Class<?> requiredType = descriptor.getDependencyType();// <1> 尝试获取一个 @Primary 注解标注的 Bean,如果有找到多个则会抛出异常String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);// <2> 如果第 `1` 步找到了则直接返回if (primaryCandidate != null) {return primaryCandidate;}// <3> 尝试找到 @Priority 注解优先级最高的那个 Bean,如果存在相同的优先级则会抛出异常String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);// <4> 如果第 `3` 步找到了则直接返回if (priorityCandidate != null) {return priorityCandidate;}// Fallback// <5> 兜底方法,遍历所有的 Beanfor (Map.Entry<String, Object> entry : candidates.entrySet()) {String candidateName = entry.getKey();Object beanInstance = entry.getValue();// <5.1> 如果满足下面其中一个条件则直接返回if ((beanInstance != null&& this.resolvableDependencies.containsValue(beanInstance)) // 该 Bean 为 Spring 内部可处理的 Bean,例如 ApplicationContext|| matchesBeanName(candidateName, descriptor.getDependencyName())) { // 名称相匹配return candidateName;}}// <6> 上面都没选出来则返回一个空对象return null;}
如果找到了多个匹配的依赖注入对象,则需要找到最匹配的那个 Bean,过程大致如下:
- 尝试获取一个
@Primary
注解标注的 Bean,如果有找到多个则会抛出异常
- 如果第
1
步找到了则直接返回
- 尝试找到
@Priority
注解优先级最高的那个 Bean,如果存在相同的优先级则会抛出异常
- 如果第
3
步找到了则直接返回
- 兜底方法,遍历所有的 Bean如果满足下面其中一个条件则直接返回:该 Bean 为 Spring 内部可处理的 Bean(例如 ApplicationContext、BeanFactory)、名称相匹配
总结
本文讲述了
@Autowired
、
@Value
和
@Resource
等注解的实现原理,在《Bean 的创建过程》中我们可以了解到,在 Spring Bean 生命周期的很多阶段都可以通过相应的 BeanPostProcessor 处理器进行扩展,其中《Bean 的属性填充阶段》会通过
InstantiationAwareBeanPostProcessor
对 Bean 进行处理,有以下两个处理器:
- AutowiredAnnotationBeanPostProcessor,主要处理
@Autowired
和
@Value
注解进行依赖注入
- CommonAnnotationBeanPostProcessor,主要处理
@Resource
注解进行依赖注入,以及
@PostConstruct
和
@PreDestroy
生命周期注解的处理
原理就是找到注解标注的字段(或方法),创建对应的注入元信息对象,然后根据该元信息对象进行注入(反射机制),底层都是通过
DefaultListableBeanFactory#resolveDependency
方法实现的,找到符合条件的 Bean(根据类型),然后筛选出最匹配的那个依赖注入对象。
疑问:@Bean 等注解的实现原理又是怎样的呢?别急,在后续文章进行分析