@Resource依赖注入原理

spring可以通过@Resource注解注入依赖,和@Autowired存在区别:

  1. @Autowired默认按类型注入,而@Resource默认按名称和类型结合注入
  2. @Autowired支持通过属性required设置为非必须注入,当依赖不存在时不会报错;@Resource注解不支持
  3. @Autowired能够配合@Qualifier@Primary@Priority共同使用

那么spring实现@Resource注解注入依赖的原理是什么,现在可以看下,逻辑不复杂,先判断容器中是否包含需要注入的依赖bean实例对象,没有的话就跟@Autowired解析注入的依赖的方式一样,可以看我前一篇**@Autowired依赖注入原理**,存在的话则到容器中根据name和type获取依赖bean实例对象。

java 复制代码
	protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
			throws NoSuchBeanDefinitionException {
......
		if (factory instanceof AutowireCapableBeanFactory) {
			AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
			DependencyDescriptor descriptor = element.getDependencyDescriptor();
			//容器中没有依赖bean实例对象,则走@Autowired自动注入逻辑
			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");
				}
			}
			//到容器中获取根据name和type获取bean实例对象
			else {
				resource = beanFactory.resolveBeanByName(name, descriptor);
				autowiredBeanNames = Collections.singleton(name);
			}
		}
		else {
			resource = factory.getBean(name, element.lookupType);
			autowiredBeanNames = Collections.singleton(name);
		}
......
		return resource;
	}
	//调用BeanFactory的getBean方法根据name和type获取bean实例对象
	public Object resolveBeanByName(String name, DependencyDescriptor descriptor) {
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			return getBean(name, descriptor.getDependencyType());
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

获取到依赖bean实例对象后,就会以反射方式set到字段中,进而完成依赖注入。这里可以看出@Resource获取依赖再注入到字段的逻辑相对简单,虽然使用起来没有@Autowired灵活,但是效率会高很多。

java 复制代码
		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();
				}
			}
		}

总结下,spring处理通过@Resource注解注入依赖时,会到容器中根据name和type获取依赖bean实例对象,再反射set注入,更多请关注微信公众号 葡萄开源

相关推荐
毕设源码-邱学长1 小时前
【开题答辩全过程】以 基于Springboot的酒店住宿信息管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
咖啡啡不加糖2 小时前
Grafana 监控服务指标使用指南:打造可视化监控体系
java·后端·grafana
gAlAxy...3 小时前
SpringBoot Servlet 容器全解析:嵌入式配置与外置容器部署
spring boot·后端·servlet
BYSJMG3 小时前
计算机毕业设计选题推荐:基于Hadoop的城市交通数据可视化系统
大数据·vue.js·hadoop·分布式·后端·信息可视化·课程设计
BYSJMG3 小时前
Python毕业设计选题推荐:基于大数据的美食数据分析与可视化系统实战
大数据·vue.js·后端·python·数据分析·课程设计·美食
东东5163 小时前
OA自动化居家办公管理系统 ssm+vue
java·前端·vue.js·后端·毕业设计·毕设
程序员鱼皮4 小时前
前特斯拉 AI 总监:AI 编程最大的谎言,是 “提效”
前端·后端·ai·程序员·开发
好好研究4 小时前
SpringBoot使用外置Tomcat
spring boot·后端·tomcat
索荣荣5 小时前
Spring Boot 实现DOCX转PDF(基于docx4j的轻量级开源方案)
spring boot·后端·pdf
mit6.8245 小时前
[todo]10个常见的后端框架
后端