Spring DI源码分析6--Autowired和Response注解的处理

本文深入分析Spring框架中依赖注入的实现原理,详细介绍了CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor如何处理@Resource和@Autowired注解,包括元数据的构建、注入过程及缓存机制。

在上一篇(DI源码分析5)中,在AbstractAutowireCapableBeanFactory#populateBean中会设置bean的属性,其中在InstantiationAwareBeanPostProcessor#postProcessPropertyValues的地方会处理依赖的属性值

CommonAnnotationBeanPostProcessor处理标注了@Resource注解

//CommonAnnotationBeanPostProcessor#postProcessPropertyValues
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		//获取@Resource注解中配置的属性值元数据
		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;
	}

获取@Resource注解中配置的属性值元数据

private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
		//缓存
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		//先从容器缓存中查找
		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 = buildResourceMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

构建@Resource的元数据

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
		Class<?> targetClass = clazz;

		do {
			final LinkedList<InjectionMetadata.InjectedElement> currElements =
					new LinkedList<>();

			//处理标注注解的属性
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//javax.xml.ws.WebServiceRef 注解
				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));
				}
				//javax.ejb.EJB 注解
				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));
				}
				//Resource 注解
				else if (field.isAnnotationPresent(Resource.class)) {
					if (Modifier.isStatic(field.getModifiers())) {
						throw new IllegalStateException("@Resource annotation is not supported on static fields");
					}
					if (!ignoredResourceTypes.contains(field.getType().getName())) {
						currElements.add(new ResourceElement(field, field, null));
					}
				}
			});

			// 处理标注注解的方法   setter方法
			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 (!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);
	}

注入元数据的构造方法

	//org.springframework.beans.factory.annotation.InjectionMetadata#InjectionMetadata
	public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {
		this.targetClass = targetClass;
		this.injectedElements = elements;
	}

同上,AutowiredAnnotationBeanPostProcessor处理Autowired注解的属性,方法

	//org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

		//获取指定类中autowire相关注解的元信息
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			//对Bean的属性进行自动注入
			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;
	}

获取给定类的autowire相关注解元信息

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	//首先从容器中查找是否有给定类的autowire相关注解元信息
	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);
				}
				//解析给定类autowire相关注解元信息
				metadata = buildAutowiringMetadata(clazz);
				//将得到的给定类autowire相关注解元信息存储在容器缓存中
				this.injectionMetadataCache.put(cacheKey, metadata);
			}
		}
	}
	return metadata;
}

解析给定类autowire相关注解元信息

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
	LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
	Class<?> targetClass = clazz;

	do {
		final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();

		//处理属性
		ReflectionUtils.doWithLocalFields(targetClass, field -> {
			//获取属性上的注解
			AnnotationAttributes ann = findAutowiredAnnotation(field);
			if (ann != null) {
				//如果给定属性是静态的,则直接遍历下一个属性
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isWarnEnabled()) {
						logger.warn("Autowired annotation is not supported on static fields: " + field);
					}
					return;
				}
				//判断注解的required属性值是否有效
				boolean required = determineRequiredStatus(ann);
				//加入元素集合
				currElements.add(new AutowiredFieldElement(field, required));
			}
		});

		//处理方法
		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				return;
			}
			AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
				if (Modifier.isStatic(method.getModifiers())) {
					if (logger.isWarnEnabled()) {
						logger.warn("Autowired annotation is not supported on static methods: " + method);
					}
					return;
				}
				if (method.getParameterCount() == 0) {
					if (logger.isWarnEnabled()) {
						logger.warn("Autowired annotation should only be used on methods with parameters: " +
								method);
					}
				}
				boolean required = determineRequiredStatus(ann);
				//获取当前方法的属性描述符,即方法是可读的(readable)getter方法,还是可写的(writeable)setter方法
				PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
				//将方法元信息封装添加到返回的元信息集合中
				currElements.add(new AutowiredMethodElement(method, required, pd));
			}
		});

		//将当前类的注解元信息存放到注解元信息集合中
		elements.addAll(0, currElements);
		//获取给定类的父类
		targetClass = targetClass.getSuperclass();
	}
	//遍历父类
	while (targetClass != null && targetClass != Object.class);
	//封装注入元数据  并返回
	return new InjectionMetadata(clazz, elements);
}

获取给定对象的autowire相关注解

	private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
		if (ao.getAnnotations().length > 0) {
			//遍历所有相关的注解:@Autowire、@Value、javax.inject.Inject
			for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
				//获取给定对象上的指定类型的注解
				AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
				if (attributes != null) {
					return attributes;
				}
			}
		}
		return null;
	}

获取当前方法的属性描述符,即方法是可读的(readable)getter方法,还是可写的(writeable)setter方法

	public static PropertyDescriptor findPropertyForMethod(Method method, Class<?> clazz) throws BeansException {
		Assert.notNull(method, "Method must not be null");
		PropertyDescriptor[] pds = getPropertyDescriptors(clazz);
		for (PropertyDescriptor pd : pds) {
			if (method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())) {
				return pd;
			}
		}
		return null;
	}

调用元数据的注入方法对属性,方法执行注入

	//org.springframework.beans.factory.annotation.InjectionMetadata#inject
	public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			boolean debug = logger.isDebugEnabled();
			//这里数个循环,会对属性,方法进行注入
			for (InjectedElement element : elementsToIterate) {
				if (debug) {
					logger.debug("Processing injected element of bean '" + beanName + "': " + element);
				}//注入在下一篇讲
				element.inject(target, beanName, pvs);
			}
		}
	}
对属性注入
	//org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
	protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			//获取注入元素对象
			Field field = (Field) this.member;
			Object value;
			//如果缓存中有
			if (this.cached) {
				//根据Bean名称解析缓存中的属性值
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			//如果当前对象没有被容器缓存
			else {
				//属性依赖描述符
				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 {
					//根据容器中Bean定义,解析指定的依赖关系,获取依赖对象
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
					//如果当前对象没有被容器缓存
					if (!this.cached) {
						//获取到了当前对象的依赖对象,并且required属性为true
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							//为指定Bean注册依赖Bean
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								//如果容器中有指定名称的Bean对象
								if (beanFactory.containsBean(autowiredBeanName)) {
									//依赖对象类型和属性类型匹配,默认按类型注入
									if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
										//创建一个依赖对象的引用,同时缓存
										this.cachedFieldValue = new ShortcutDependencyDescriptor(
												desc, autowiredBeanName, field.getType());
									}
								}
							}
						}
						//如果获取的依赖关系为null,且获取required属性为false
						else {
							//将属性值的缓存设置为null
							this.cachedFieldValue = null;
						}
						//容器已经对当前属性的值缓存
						this.cached = true;
					}
				}
			}
			//如果属性依赖值不为null
			if (value != null) {
				//反射,设置自动的访问控制权限为允许访问
				ReflectionUtils.makeAccessible(field);
				//反射,为Bean对象的属性设置值
				field.set(bean, value);
			}
		}
	}
对方法注入
	//org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject
	protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		//如果属性被显式设置为skip,则不进行注入
		if (checkPropertySkipping(pvs)) {
			return;
		}
		//获取注入元素
		Method method = (Method) this.member;
		Object[] arguments;
		//如果有缓存
		if (this.cached) {
			//获取缓存中指定Bean名称的方法参数
			arguments = resolveCachedArguments(beanName);
		}
		//没有缓存
		else {
			//获取方法的参数列表
			Class<?>[] paramTypes = method.getParameterTypes();
			//创建一个存放方法参数的数组
			arguments = new Object[paramTypes.length];
			//依赖描述符
			DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
			Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
			Assert.state(beanFactory != null, "No BeanFactory available");
			//获取容器的类型转换器
			TypeConverter typeConverter = beanFactory.getTypeConverter();
			for (int i = 0; i < arguments.length; i++) {
				//创建方法参数对象
				MethodParameter methodParam = new MethodParameter(method, i);
				//解析方法的输入参数,为方法参数创建依赖描述符
				DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
				currDesc.setContainingClass(bean.getClass());
				descriptors[i] = currDesc;
				try {
					//根据容器中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);
				}
			}
			synchronized (this) {
				//如果当前方法没有被容器缓存
				if (!this.cached) {
					//如果方法的参数列表不为空
					if (arguments != null) {
						//为容器中缓存方法参数的对象赋值
						Object[] cachedMethodArguments = new Object[paramTypes.length];
						for (int i = 0; i < arguments.length; i++) {
							cachedMethodArguments[i] = descriptors[i];
						}
						//为指定Bean注册依赖Bean
						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();
								//容器中存在指定名称的Bean对象
								if (beanFactory.containsBean(autowiredBeanName)) {
									//参数类型和依赖对象类型匹配
									if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
										//创建一个依赖对象的引用,复制给方法相应的参
										cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
												descriptors[i], autowiredBeanName, paramTypes[i]);
									}
								}
							}
						}
						this.cachedMethodArguments = cachedMethodArguments;
					}
					//如果方法参数列表为null,则设置容器对该方法参数的缓存为null
					else {
						this.cachedMethodArguments = null;
					}
					//设置容器已经对该方法缓存
					this.cached = true;
				}
			}
		}
		//方法参数依赖对象不为null
		if (arguments != null) {
			try {
				//反射,显式设置方法的访问控制权限为允许访问
				ReflectionUtils.makeAccessible(method);
				//反射调用Bean的方法
				method.invoke(bean, arguments);
			}
			catch (InvocationTargetException ex){
				throw ex.getTargetException();
			}
		}
	}
<think>嗯,用户问的是Java注解Spring注解,我需要先理清楚这两者的区别联系。首先,Java注解Java语言本身的一个特性,而Spring注解Spring框架基于Java注解扩展的。用户可能对这两个概念有点混淆,或者想了解它们之间的关系以及具体用途。 我应该先解释Java注解的基本概念,包括它们的定义、用途以及如何自定义注解。然后,再介绍Spring注解,说明Spring如何利用这些注解来简化配置实现各种功能,比如依赖注入、事务管理等。需要举例说明常见的注解,比如@Component、@Autowired,这样用户更容易理解。 用户可能是在学习Spring框架时遇到了这些注解,或者在实际开发中需要用到,但不太清楚它们的作用区别。需要确保解释清晰,结构分明,避免技术术语过于复杂,同时覆盖常见的注解例子。另外,用户可能还希望了解如何自定义注解,这部分虽然可能高级一些,但简要提及可以满足更多需求。 要注意用户提到的格式要求,所有行内数学表达式用$...$,但这里可能用不上数学公式。不过要确保LaTeX语法正确,如果有涉及的话。回答结构要分点,帮助用户逐步理解,先JavaSpring,再两者的对比,最后总结应用场景。确保内容真实可靠,参考官方文档或权威资料,避免错误信息。</think>好的,我将分步骤为您解析Java注解Spring注解的核心概念及关联: 一、Java注解的本质(语言级特性) 1. 定义:Java注解(Annotation)是JDK5引入的元数据机制,语法为`@AnnotationName` 2. 核心作用: - 代码标记:提供编译期检查(如`@Override`) - 配置信息:替代XML配置(如`@WebServlet`) - 运行时处理:通过反射读取(需配合`@Retention(RetentionPolicy.RUNTIME)`) 3. 元注解(定义注解注解): ```java @Target(ElementType.METHOD) // 作用目标 @Retention(RetentionPolicy.RUNTIME) // 生命周期 public @interface MyAnnotation { String value() default ""; // 注解参数 } ``` 二、Spring注解的扩展(框架级实现) 1. 核心机制:基于Java注解体系扩展,实现IoC/DIAOP 2. 常用注解分类: | 类别 | 注解示例 | 功能说明 | |------------|-----------------------|----------------------------| | 组件扫描 | `@Component` | 通用组件标识 | | | `@Service` | 服务层标识 | | | `@Repository` | 数据层标识 | | 依赖注入 | `@Autowired` | 按类型自动装配 | | | `@Qualifier` | 按名称精确装配 | | 配置相关 | `@Configuration` | 声明配置类 | | | `@Bean` | 定义Bean对象 | | AOP相关 | `@Aspect` | 声明切面类 | | | `@Before/@After` | 定义通知类型 | | Web相关 | `@RestController` | REST控制器 | | | `@RequestMapping` | 请求映射配置 | 三、关键差异对比 1. 作用域差异: - Java注解:语言基础功能,适用于任何Java场景 - Spring注解:专为Spring框架设计,依赖Spring容器 2. 处理机制差异: ```java // Java注解处理示例(反射机制) if(method.isAnnotationPresent(MyAnnotation.class)) { // 注解处理逻辑 } // Spring注解处理(容器级处理) @Component public class MyBean { @Autowired // 由Spring容器完成依赖注入 private Dependency dep; } ``` 四、实际应用场景 1. 组合使用示例: ```java @RestController // Spring注解 @RequestMapping("/api") // Spring注解 public class UserController { @Autowired // Spring依赖注入 private UserService userService; @GetMapping("/{id}") // Spring Web注解 @ResponseStatus(HttpStatus.OK) // Spring状态注解 public User getUser(@PathVariable Long id) { // Spring参数注解 return userService.findById(id); } } ``` 五、最佳实践建议 1. 优先使用Spring标准注解,保证框架兼容性 2. 复杂配置场景建议组合使用注解Java Config 3. 自定义注解时应明确生命周期(SOURCE/CLASS/RUNTIME) 理解这两个层次的注解体系,可以帮助开发者更高效地使用Spring框架进行企业级应用开发,同时掌握元注解机制也为自定义扩展提供了技术基础。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值