从源码层面带你实现一个自动注入注解

本文详细剖析了Spring框架中`@Autowired`注解的实现过程,包括`InjectionMetadata`的使用、`AutowiredFieldElement`和`AutowiredMethodElement`的作用,以及自定义注解的处理。主要涉及元数据注入、依赖查找和对象构建等内容。
摘要由CSDN通过智能技术生成

}

/省略代码/

  • 真正注入数据的是 metadata.inject(bean, beanName, pvs);

  • 调用的是 InjectionMetadata#inject 方法

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

Collection checkedElements = this.checkedElements;

// 带有注解的方法或者属性列表

Collection elementsToIterate =

(checkedElements != null ? checkedElements : this.injectedElements);

if (!elementsToIterate.isEmpty()) {

for (InjectedElement element : elementsToIterate) {

element.inject(target, beanName, pvs);

}

}

}

  • 循环调用之前加入的带有注解的方法或者属性构建的对象 AutowiredFieldElement#inject, AutowiredMethodElement#inject

/**

  • 属性上有注解 构建的处理对象

*/

private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

private final boolean required;

private volatile boolean cached;

@Nullable

private volatile Object cachedFieldValue;

public AutowiredFieldElement(Field field, boolean required) {

super(field, null);

this.required = required;

}

@Override

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

// 获取属性名

Field field = (Field) this.member;

Object value;

// Bean 不是单例的话,会重复进入注入的这个操作,

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 {

// 首次创建的时候进入该方法

value = resolveFieldValue(field, bean, beanName);

}

if (value != null) {

// 属性如果不为public的话,则设置为可访问

ReflectionUtils.makeAccessible(field);

field.set(bean, value);

}

}

@Nullable

private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {

// 构建DependencyDescriptor对象

DependencyDescriptor desc = new DependencyDescriptor(field, this.required);

desc.setContainingClass(bean.getClass());

// 注入bean的数量。 有可能字段上是一个List

Set autowiredBeanNames = new LinkedHashSet<>(1);

Assert.state(beanFactory != null, “No BeanFactory available”);

// 获得beanFactory类型转换类

TypeConverter typeConverter = beanFactory.getTypeConverter();

Object value;

try {

// 查找依赖关系

value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

}

catch (BeansException ex) {

throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);

}

synchronized (this) {

if (!this.cached) {

Object cachedFieldValue = null;

if (value != null || this.required) {

cachedFieldValue = desc;

// 填入依赖关系

registerDependentBeans(beanName, autowiredBeanNames);

// 判断如果注入依赖是只有一个

if (autowiredBeanNames.size() == 1) {

String autowiredBeanName = autowiredBeanNames.iterator().next();

if (beanFactory.containsBean(autowiredBeanName) &&

beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {

cachedFieldValue = new ShortcutDependencyDescriptor(

desc, autowiredBeanName, field.getType());

}

}

}

this.cachedFieldValue = cachedFieldValue;

this.cached = true;

}

}

return value;

}

}

/**

  • 方法上有注解 构建的处理对象

*/

private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {

private final boolean required;

private volatile boolean cached;

@Nullable

private volatile Object[] cachedMethodArguments;

public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {

super(method, pd);

this.required = required;

}

@Override

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

// 检查属性是不会在之前就已经注入过了。如果主如果则不进行二次覆盖

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 {

// 属性如果不为public的话,则设置为可访问

ReflectionUtils.makeAccessible(method);

// 调用方法 并传入参数

method.invoke(bean, arguments);

}

catch (InvocationTargetException ex) {

throw ex.getTargetException();

}

}

}

@Nullable

private Object[] resolveCachedArguments(@Nullable String beanName) {

Object[] cachedMethodArguments = this.cachedMethodArguments;

if (cachedMethodArguments == null) {

return null;

}

Object[] arguments = new Object[cachedMethodArguments.length];

for (int i = 0; i < arguments.length; i++) {

arguments[i] = resolvedCachedArgument(beanName, cachedMethodArguments[i]);

}

return arguments;

}

@Nullable

private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {

// 获取方法上有几个参数

int argumentCount = method.getParameterCount();

Object[] arguments = new Object[argumentCount];

DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];

Set autowiredBeans = new LinkedHashSet<>(argumentCount);

Assert.state(beanFactory != null, “No BeanFactory available”);

TypeConverter typeConverter = beanFactory.getTypeConverter();

for (int i = 0; i < arguments.length; i++) {

// 方法参数,从方法参数中取出 i 构造 MethodParameter 对象

MethodParameter methodParam = new MethodParameter(method, i);

DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);

currDesc.setContainingClass(bean.getClass());

descriptors[i] = currDesc;

try {

// 获取方法中 i 参数的内容

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);

}

}

synchronized (this) {

if (!this.cached) {

if (arguments != null) {

DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);

registerDependentBeans(beanName, autowiredBeans);

if (autowiredBeans.size() == argumentCount) {

Iterator it = autowiredBeans.iterator();

Class<?>[] paramTypes = method.getParameterTypes();

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;

}

}

return arguments;

}

}

  • 以上就是 @Autowired 实现的完整流程。 可概括为:

populateBean -> AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues

-> 获取带有注解的属性和方法构建 AutowiredFieldElement, AutowiredMethodElement 对象,然后循环调用了 inject 进行属性调用

自定义自动注入注解。


  • 编写抽象类代码:

package com.yunlongn.common.core.autowired;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeansException;

import org.springframework.beans.PropertyValues;

import org.springframework.beans.factory.*;

import org.springframework.beans.factory.annotation.InjectionMetadata;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

import org.springframework.core.annotation.AnnotationUtils;

import org.springframework.core.annotation.MergedAnnotation;

import org.springframework.core.annotation.MergedAnnotations;

import org.springframework.lang.Nullable;

import org.springframework.util.ReflectionUtils;

import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;

import java.lang.annotation.Annotation;

import java.lang.reflect.*;

import java.util.*;

import java.util.concurrent.ConcurrentHashMap;

/**

  • 抽象的自动注入方法

  • @author yunlgongn

*/

public abstract class AbstractAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

private final Set<Class<? extends Annotation>> annotationTypes = new LinkedHashSet<>(4);

private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);

protected final Log logger = LogFactory.getLog(getClass());

/**

  • 处理的 annotationType 对象

  • @return Annotation 自定义注解

*/

public abstract Class<? extends Annotation> annotationType();

AbstractAnnotationBeanPostProcessor () {

Class<? extends Annotation> annotation = this.annotationType();

annotationTypes.add(annotation);

}

@Override

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {

return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);

}

@Override

public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {

return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);

}

@Override

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {

InjectionMetadata metadata = findAbstractMetadata(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;

}

private InjectionMetadata findAbstractMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {

String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());

InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);

// 获取是否已经读取过这个 class 类的 InjectionMetadata 有的话直接从缓存中获取出去

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 = buildAbstractMetadata(clazz);

this.injectionMetadataCache.put(cacheKey, metadata);

}

}

}

return metadata;

}

private InjectionMetadata buildAbstractMetadata(final Class<?> clazz) {

if (!AnnotationUtils.isCandidateClass(clazz, this.annotationTypes)) {

return InjectionMetadata.EMPTY;

}

List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();

Class<?> targetClass = clazz;

do {

final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

// 循环 targetClass 的所有 field 并执 FieldCallback 逻辑 (函数式编程接口,传入的是一个执行函数)

ReflectionUtils.doWithLocalFields(targetClass, field -> {

// 获得字段上面的 Annotation 注解

MergedAnnotation<?> ann = findAbstractAnnotation(field);

if (ann != null) {

// 判断是否为静态属性 如果是,则不进行注入

if (Modifier.isStatic(field.getModifiers())) {

if (logger.isInfoEnabled()) {

logger.info("Abstract annotation is not supported on static fields: " + field);

}

return;

}

currElements.add(new AbstractFieldElement(field, ann));

}

});

//数据加到数组最前方 父类的的注解都放在靠前的位置

elements.addAll(0, currElements);

targetClass = targetClass.getSuperclass();

}

while (targetClass != null && targetClass != Object.class);

return InjectionMetadata.forElements(elements, clazz);

}

@Nullable

private MergedAnnotation<?> findAbstractAnnotation(AccessibleObject ao) {

// 将指定方法上的注解合并成一个注解

MergedAnnotations annotations = MergedAnnotations.from(ao);

// 循环要扫描的注解 annotationTypes 那个在前面就认哪个

for (Class<? extends Annotation> type : this.annotationTypes) {

MergedAnnotation<?> annotation = annotations.get(type);

if (annotation.isPresent()) {

return annotation;

}

}

return null;

}

@Deprecated

@Override

public PropertyValues postProcessPropertyValues(

PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {

return postProcessProperties(pvs, bean, beanName);

}

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);

}

/**

  • 实现交给子类进行实现 将注解透传出去

  • @param mergedAnnotation 属性上的注解

  • @param bean bean实例

  • @param beanName bean的名字

  • @param field 字段

  • @param autowiredFieldElement 注解

  • @return 注入对象

  • @throws Exception

*/

protected abstract Object getInjectedObject(MergedAnnotation<?> mergedAnnotation, Object bean, String beanName, Field field,

AbstractFieldElement autowiredFieldElement) throws Exception;

public class AbstractFieldElement extends InjectionMetadata.InjectedElement {

private final MergedAnnotation<?> mergedAnnotation;

public AbstractFieldElement(Field field, MergedAnnotation<?> mergedAnnotation) {

super(field, null);

this.mergedAnnotation = mergedAnnotation;

}

@Override

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

Field field = (Field) this.member;

Object value = getInjectedObject(this.mergedAnnotation, bean, beanName, field, this);

if (value != null) {

ReflectionUtils.makeAccessible(field);

field.set(bean, value);

}

}

}

}

  • 抽象类实现,实现一个 @RedisAutowired 自定义注入注解

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

Java核心架构进阶知识点

面试成功其实都是必然发生的事情,因为在此之前我做足了充分的准备工作,不单单是纯粹的刷题,更多的还会去刷一些Java核心架构进阶知识点,比如:JVM、高并发、多线程、缓存、Spring相关、分布式、微服务、RPC、网络、设计模式、MQ、Redis、MySQL、设计模式、负载均衡、算法、数据结构、kafka、ZK、集群等。而这些也全被整理浓缩到了一份pdf——《Java核心架构进阶知识点整理》,全部都是精华中的精华,本着共赢的心态,好东西自然也是要分享的

image

image

image

内容颇多,篇幅却有限,这就不在过多的介绍了,大家可根据以上截图自行脑补
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
.(img-i1375HXi-1713512103502)]

[外链图片转存中…(img-DnafCVBN-1713512103503)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

Java核心架构进阶知识点

面试成功其实都是必然发生的事情,因为在此之前我做足了充分的准备工作,不单单是纯粹的刷题,更多的还会去刷一些Java核心架构进阶知识点,比如:JVM、高并发、多线程、缓存、Spring相关、分布式、微服务、RPC、网络、设计模式、MQ、Redis、MySQL、设计模式、负载均衡、算法、数据结构、kafka、ZK、集群等。而这些也全被整理浓缩到了一份pdf——《Java核心架构进阶知识点整理》,全部都是精华中的精华,本着共赢的心态,好东西自然也是要分享的

[外链图片转存中…(img-3H1YsnnM-1713512103503)]

[外链图片转存中…(img-jdSEQbd4-1713512103503)]

[外链图片转存中…(img-ucT8TbGA-1713512103503)]

内容颇多,篇幅却有限,这就不在过多的介绍了,大家可根据以上截图自行脑补
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值