Spring @Autowired 注解原理

这篇具有很好参考价值的文章主要介绍了Spring @Autowired 注解原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring @Autowired 注解原理

1.@Autowired 使用

@ComponentScan("org.example.bean")
public class AnnoContextDemo {

    @Autowired
    private User user;


    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnoContextDemo.class);

        User user1 = context.getBean(AnnoContextDemo.class).user;

        System.out.println("user1 = " + user1);
    }


}

被扫描的组件配置类

@Configuration
public class BeanConfig {

    @Bean
    public User user(){
        return new User(21,"张三");
    }

}

输出结果

user1 = User{age=21, name='张三'}

2.依赖自动注入原理

定位@Autowired所在包 org.springframework.beans.factory.annotation.Autowired

找到同包下 AutowiredAnnotationBeanPostProcessor

Spring @Autowired 注解原理,spring,java,后端

AutowiredAnnotationBeanPostProcessor 的类继承图如下

Spring @Autowired 注解原理,spring,java,后端

AutowiredAnnotationBeanPostProcessor实现了InstantiationAwareBeanPostProcessor与

MergedBeanDefinitionPostProcessor两个BeanPostProcessor后置处理器接口

  1. MergedBeanDefinitionPostProcessor 此接口主要有两个方法 抽象方法 postProcessMergedBeanDefinition 默认方法 resetBeanDefinition

  2. InstantiationAwareBeanPostProcessor 此接口 抽象方法 postProcessBeforeInstantiation ,postProcessAfterInstantiation ,默认方法 postProcessProperties ,默认过时方法 postProcessPropertyValues

想搞清楚@Autowried注入原理,先得知道这些接口对应方法执行的先后顺序 跟踪ApplicationContext.refresh方法,调用链路如下

ApplicationContext.refresh() -> AbstractApplicationContext.finishBeanFactoryInitialization() -> ConfigurableListableBeanFactory.preInstantiateSingletons() - > AbstractBeanFactory.getBean() -> AbstractBeanFactory.doGetBean() -> AbstractBeanFactory.getSingleton() -> AbstractBeanFactory.createBean()

实例化前

-> resolveBeforeInstantiation() 执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()前置方法 如果返回不为null,将执行 InstantiationAwareBeanPostProcessor.postProcessAfterInitialization()后置方法。

创建bean实例阶段

-> doCreateBean() -> createBeanInstance 反射创建bean实例

-> applyMergedBeanDefinitionPostProcessors() 执行 MergedBeanDefinitionPostProcessor.MergedBeanDefinitionPostProcessor方法 合并bean定义信息

属性注入阶段

-> populateBean() -> 执行 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 后置处理方法 -> 执行InstantiationAwareBeanPostProcessor.postProcessProperties -> InstantiationAwareBeanPostProcessor.postProcessPropertyValues -> applyPropertyValues 执行属性注入

初始化阶段

-> initializeBean() -> BeanPostProcessor.postProcessBeforeInitialization() 执行前置方法 -> invokeInitMethods() 反射调用初始化方法 -> BeanPostProcessor.postProcessAfterInitialization 执行后置方法

收尾注册bean

->registerDisposableBeanIfNecessary() 注册bean

通过上面追踪refresh()方法我们可知,spring容器将先调用 AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition方法,然后执行 postProcessProperties 方法

3. postProcessMergedBeanDefinition 查找需要自动注入的字段或方法

	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

进入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.
		String 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);
					}
					//查找类的字段,方法,是否有需要自动注入对象的元素,封装InjectionMetadata
					metadata = buildAutowiringMetadata(clazz);
					//放入缓存中,供后面调用取出
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

进入 buildAutowiringMetadata 方法

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
		//判断当前类是否有使用autowiredAnnotationTypes容器中的注解
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
			//反射遍历类中所有字段
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//字段上是否有标注自动装配相关的注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					//封装InjectionMetadata
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});
			
			//反射遍历类中所有方法
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
					//方法上是否有标注自动装配相关的注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					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);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					//封装InjectionMetadata
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return InjectionMetadata.forElements(elements, clazz);
	}

this.autowiredAnnotationTypes 为set集合,容器内为需要自动注入的注解类

private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
	public AutowiredAnnotationBeanPostProcessor() {
	## 1.@Autowired
		this.autowiredAnnotationTypes.add(Autowired.class);
  ## 2.@Value
		this.autowiredAnnotationTypes.add(Value.class);
		try {
 ## 3.@javax.inject.Inject  JSR-330规范中定义的一个注解
			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.
		}
	}

4.postProcessProperties 需要自动注入的元素从容器中获取bean后注入

	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		//首先从缓存中取出需要自动注入的元素(包括字段,方法)
		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;
	}

进入 metadata.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()) {
			//遍历需要注入的元素
			for (InjectedElement element : elementsToIterate) {
				//不同类型调用各自inject方法
				element.inject(target, beanName, pvs);
			}
		}
	}

字段处理逻辑

通过 resolveFieldValue 方法,找到需要依赖的bean(单个或集合),通过 Filed.set方法注入

		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			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 {
			//查找依赖的bean
				value = resolveFieldValue(field, bean, beanName);
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				//反射设置值
				field.set(bean, value);
			}
		}

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			Class<?> type = descriptor.getDependencyType();
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					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 {
					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()));
				}
			}
		
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			//字段非集合类型时bean时查找方法
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						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;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (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());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

findAutowireCandidates() 会调用 BeanFactoryUtils.beanNamesForTypeIncludingAncestors

底层通过类似双亲委派模型,找出所有的bean文章来源地址https://www.toymoban.com/news/detail-579069.html

	public static String[] beanNamesForTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
		if (lbf instanceof HierarchicalBeanFactory) {
			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
				String[] parentResult = beanNamesForTypeIncludingAncestors(
						(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		return result;
	}

到了这里,关于Spring @Autowired 注解原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 为什么Spring和IDEA不推荐使用@Autowired注解,有哪些替代方案?

    在使用Spring框架和JetBrains IDEA集成开发环境(IDE)进行Java开发时,你可能经常会遇到@Autowired注解。@Autowired是Spring框架中用于实现依赖注入的核心注解之一。然而,近年来,Spring和IDEA都不再推荐使用@Autowired注解,并提出了更好的替代方案。本文将详细分析为什么Spring和IDEA不

    2024年02月07日
    浏览(51)
  • Spring和IDEA都不推荐用的@Autowired注解,为什么还有那么多人用?

    @Autowired的默认装配 我们都知道在spring中@Autowired注解,是用来自动装配对象的。通常,我们在项目中是这样用的: 没错,这样是能够装配成功的,因为默认情况下spring是按照类型装配的,也就是我们所说的byType方式。 此外,@Autowired注解的required参数默认是true,表示开启自动

    2023年04月18日
    浏览(49)
  • spring启动流程 (5) Autowired原理

    BeanClass可以在构造方法上标注@Autowired注解,Spring在创建Bean实例时将自动为其注入依赖参数 Spring会优先使用标注@Autowired注解的构造方法 当一个构造方法标注了@Autowired注解且required=true时,其余构造方法不允许再标注@Autowired注解 当多个构造方法标注了@Autowired注解且required=fa

    2024年02月16日
    浏览(35)
  • @Autowired和@Resource注解之间的关系区别,Bean的作用域和生命周期,Spring的执行流程

    目录 一. @Autowired 和 @Resource 注解 二. Bean的作用域  1. singleton(单例模式) 2. prototype(原型模式)(多例模式) 3. 请求作用域:request 4. 会话作用域:session 三. Spring 的执行流程 四. Bean 的生命周期   1. 实例化  2. 设置属性  3. Bean 初始化      3.1 执行各种各种 Aware 通知;     

    2024年02月04日
    浏览(54)
  • Spring源码学习-后置处理器,Autowired实现原理

    Autowired实现原理 populateBean 给创建好的bean实例进行普通属性的赋值 InstantiationAwareBeanPostProcessor AutowiredAnnotationBeanPostProcessor 这个就是用来完成Autowired注解能够自动装配的bean后置处理器 这个方法初始化了一个set,用来存放需要解析的自动装配注解,里面就包括Autowired,Value和Inject等

    2024年02月16日
    浏览(35)
  • 【注解使用】使用@Autowired后提示:Field injection is not recommended(Spring团队不推荐使用Field注入)

    在使用 IDEA 开发 SpringBoot 项目时,在  Controller  类中使用注解  @Autowired  注入一个依赖出现了警告提示,查看其他使用该注解的地方同样出现了警告提示。这是怎么回事?由于先去使用了SpringBoot并没有对Spring进行系统性学习,所以做一个记录。 Field injection is not recommended(

    2024年02月12日
    浏览(33)
  • Spring CORS 跨域使用与原理(@CrossOrigin注解,Java配置类方式,xml方式)

    出于安全原因,浏览器禁止AJAX调用当前源之外的资源。 跨域资源共享(CORS)是由大多数浏览器实现的W3C规范,它允许您以一种灵活的方式指定授权哪种跨域请求,而不是使用一些不太安全、功能不太强大的hack(如IFrame或JSONP)。 Spring Framework 4.2 GA为CORS提供了一流的开箱即用支持

    2024年02月08日
    浏览(49)
  • Spring Boot 学习之——@SpringBootApplication注解(自动注解原理)

    springboot是基于spring的新型的轻量级框架,最厉害的地方当属**自动配置。**那我们就可以根据启动流程和相关原理来看看,如何实现传奇的自动配置 从上面代码可以看出,Annotation定义(@SpringBootApplication)和类定义(SpringApplication.run)最为耀眼,所以要揭开SpringBoot的神秘面纱

    2024年01月25日
    浏览(42)
  • Spring Boot 中@EnableAutoConfiguration注解原理

    开启  Spring  的自动装配功能; 简单点说就是Spring Boot根据依赖中的jar包,自动选择 实例化 某些配置,配置类必须有@Configuration注解。 二、@EnableAutoConfiguration的原理 1.点进启动类上的EnableAutoConfiguration注解 2.发现@EnableAutoConfiguration注解实际上也是@Import注解实现的(其实@Ena

    2024年01月17日
    浏览(38)
  • Spring cloud负载均衡 @LoadBalanced注解原理

    接上一篇文章,案例代码也在上一篇文章的基础上。 在上一篇文章的案例中,我们创建了作为Eureka server的Eureka注册中心服务、作为Eureka client的userservice、orderservice。 orderservice引入RestTemplate,加入了@LoadBalanced注解,代码如下: 从而,我们实现了基于Eureka注册中心的微服务治

    2024年02月05日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包