一、@Autowired是什么

(1)存在范围

@Autowired注解是属于spring的容器配置的一个注解,因此@Autowired注解是一个用于Spring容器配置的注解。与它同属容器配置的注解还有:

@Primary(含义:首选项,当类型冲突情况下,此注解修饰类作为首选注入
                 位置:修饰类
                 注意:不能单独使用),

@Qualifier(value="注入的id")

含义:按照名称装配
                 位置:修饰成员变量
                 注意:不能单独使用

@Resource(name="注入的id")
            含义:按照名称装配
            位置:修饰成员变量
            注意:单独使用......等等。

(2)定义解释

@Autowired注解又称:自动装配。在Spring中,自动装配指的就是使用将Spring容器中的bean自动的和我们需要这个bean的类组装在一起。

二、什么情况下使用到@Autowired

前情回顾:使用spring开发时,进行配置Spring bean元数据主要有三种方式。

一:基于 XML 配置

二:基于 注解  配置:Spring2.5以上版本支持

三:基于Java 配置:Spring3.0以上版本支持

基于注解配置时,完成自动化装配Bean的情况下,@Autowired的使用便会使Spring自动满足bean之间的依赖注入。

三、如何使用@Autowired

(1)使用位置:修饰成员变量

@Controller
public class StudentControllerImp implements IStudentController {@Autowiredprivate IStudentService service;@Overridepublic void save() {System.out.println("======controler的新增方法=======");service.save();}
}

(2)在xml文件中完成组件扫描设置

 <!--扫描包--><context:component-scan base-package="com.apesource"></context:component-scan>

com.apesource---包名;启用组件扫描,默认当前配置类所在包为基础包

四、@Autowired注解是如何实现的

--------------------------------以下部分内容参考于相关公众号文章-----------------------------------------------

(1)打开@Autowired源码

package org.springframework.beans.factory.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {boolean required() default true;
}

我们知道: 在java中注解实现的核心技术是反射

(2)我们让看一下源代码中的元注解(也就是上面提到的注解的注解),总共有4个如下:

  • @Target,说明的是Annotation所修饰的对象范围

  • @Retention,定义了该Annotation被保留的时间长短:使用这个元注解可以对 Annotation的“生命周期”限制

  • @Documented,用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员

  • @Inherited;元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类

Autowired注解可以应用在构造方法,普通方法,参数,字段,以及注解这五种类型的地方,它的保留策略是在运行时。

(3)在Spring源代码当中,Autowired注解位于包org.springframework.beans.factory.annotation之中,该包的内容如下:

Spring对autowire注解的实现逻辑位于类:AutowiredAnnotationBeanPostProcessor之中,红色箭头所指的类。其中的核心处理代码如下:

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {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<>();//通过反射获取该类所有的字段,并遍历每一个字段,并通过方法findAutowiredAnnotation遍历每一个字段的所用注解,并如果用autowired修饰了,则返回auotowired相关属性ReflectionUtils.doWithLocalFields(targetClass, field -> {MergedAnnotation<?> ann = findAutowiredAnnotation(field);if (ann != null) {校验autowired注解是否用在了static方法上if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static fields: " + field);}return;//判断是否指定了required}boolean required = determineRequiredStatus(ann);currElements.add(new AutowiredFieldElement(field, required));}});//和上面一样的逻辑,但是是通过反射处理类的methodReflectionUtils.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);currElements.add(new AutowiredMethodElement(method, required, pd));}});//用@Autowired修饰的注解可能不止一个,因此都加在currElements这个容器里面,一起处理  elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return InjectionMetadata.forElements(elements, clazz);}

最后这个方法返回的是一个InjectionMetadata集合。由两部分组成:

一是我们处理的目标类,二就是上述方法获取到的所以elements集合。

源代码:

 private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {return InjectionMetadata.EMPTY;}List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;

有了目标类,与所有需要注入的元素集合之后,我们就可以实现autowired的依赖注入逻辑了,实现的方法如下:

源代码:

@Deprecated@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {return postProcessProperties(pvs, bean, beanName);}

它调用的方法是InjectionMetadata中定义的inject方法,如下

源代码

@Overrideprotected 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-resolvevalue = resolveFieldValue(field, bean, beanName);}}else {value = resolveFieldValue(field, bean, beanName);}if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);}}

然后调用inject方法;

源代码

@Overrideprotected 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-resolvearguments = resolveMethodArguments(method, bean, beanName);}}else {arguments = resolveMethodArguments(method, bean, beanName);}if (arguments != null) {try {ReflectionUtils.makeAccessible(method);method.invoke(bean, arguments);}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}

在这里的代码当中我们也可以看到,是inject也使用了反射技术并且依然是分成字段和方法去处理的。在代码里面也调用了makeAccessible这样的可以称之为暴力破解的方法,但是反射技术本就是为框架等用途设计的。

对于方法的话,本质就是去调用这个方法,因此这里调用的是method.invoke.

getResourceToInject方法的参数就是要注入的bean的名字,这个方法的功能就是根据这个bean的名字去拿到它。

总结:

使用@Autowired注入的bean对于目标类来说,从代码结构上来讲也就是一个普通的成员变量,@Autowired和spring一起工作,通过反射为这个成员变量赋值,将其变为实例对象。

@Autowired的原理简识相关推荐

  1. Webpack模块化原理简析

    webpack模块化原理简析 1.webpack的核心原理 一切皆模块:在webpack中,css,html.js,静态资源文件等都可以视作模块:便于管理,利于重复利用: 按需加载:进行代码分割,实现 ...

  2. Android Handler与Looper原理简析

    一直感觉自己简直就是一个弱智,最近越来越感觉是这样了,真的希望自己有一天能够认同自己,认同自己. 本文转载于:https://juejin.im/post/59083d7fda2f60005d14ef ...

  3. grpc通信原理_gRPC原理简析

    gRPC原理简析 gRPC是由谷歌提出并开发的RPC协议,gRPC提供了一套机制,使得应用程序之间可以进行通信. 降级开发者的使用门槛,屏蔽网络协议,调用对端的接口就像是调用本地的函数一样.而gRPC ...

  4. Android V1及V2签名原理简析

    Android为了保证系统及应用的安全性,在安装APK的时候需要校验包的完整性,同时,对于覆盖安装的场景还要校验新旧是否匹配,这两者都是通过Android签名机制来进行保证的,本文就简单看下Andro ...

  5. CRC原理简析——史上最清新脱俗简单易懂的CRC解析

    CRC原理简析 1. CRC校验原理 CRC校验原理根本思想就是先在要发送的帧后面附加一个数(这个就是用来校验的校验码,但要注意,这里的数也是二进制序列的,下同),生成一个新帧发送给接收端.当然,这个 ...

  6. Java的定时器Timer和定时任务TimerTask应用以及原理简析

    记录:272 场景:Java JDK自带的定时器Timer和定时任务TimerTask应用以及原理简析.在JDK工具包:java.util中可以找到源码,即java.util.Timer和java.u ...

  7. 自考计算机网络原理简答题,自考计算机网络原理简答题汇总.doc

    自考计算机网络原理简答题汇总 2013-440.TCP可用的端口号有65536个,请说明这些端口号的使用规定. P139第六章 (1)端口号小于256的定义为常用端口,服务器一般都是通过常用端口来识别 ...

  8. 转子接地保护原理_发变组转子接地保护原理简析

    发变组转子接地保护原理简析 发电机转子接地故障是常见的故障之一, 发生一点接地, 对发电机本身并不直接构成危 害,此时可通过转移负荷,平稳停机后,再查故障点:若在此基础上又发生另外一点接地, 将会严重 ...

  9. 深入浅出kafka原理-1-初识只作乍见之欢

    目录 前言: 1.由来 2.特点 3.使用场景 4.两种模式 1.Kafka名词解释 2.Kafka历史由来 版本号 3.Kafka术语 前言: 1.由来 为什么使用消息队列? 从系统之间有通信需求开 ...

最新文章

  1. vc mysql控件_VC++使用ActiveX控件连接和操作数据库
  2. 很好的linux启动说明( bootsect.S、setup.S、head.S)
  3. awgn信道中的噪声功率谱密度_从OFC2020看高级算法在光通信中的应用
  4. POJ 3648 Wedding
  5. python布尔类型运算_9.python的布尔类型与流程控制
  6. 地表上最强编程语言——C语言
  7. 解决从github上下载代码仓库慢的问题
  8. vmware tools 的安装(Read-only file system 的解决)
  9. 芒果云 在线代码编辑器
  10. The essense of the software atchitecture
  11. 奇妙的裴波那契数列和黄金分割
  12. 原生JavaScript实现entries和fromEntries
  13. 跟领导汇报工作时,这句话建议你不要说
  14. 基于unity自己写光追。
  15. maya计算机内存不足请保存,Word突然出现无法保存内存不足怎么办
  16. 2022暑期项目实训(二)
  17. 实现系统滚动条换肤功能
  18. raspberry pi_我如何从Mac Mini迁移到Raspberry Pi
  19. 关于秘密共享方案的实例(shamir)
  20. 【项目管理】采购、外包、合同

热门文章

  1. [安全] AD域解释 , 域和组的区别?
  2. 攻防世界we区newer题目
  3. 2019计算机小高考成绩,小高考没过怎么办 2021小高考难度如何
  4. 前端项目微金所1 - bootstrap模板,Compatible(兼容),Viewport(视口),条件注释,第三方依赖,MediaQuery媒体查询...
  5. Mysql主从同步报错解决:Error executing row event: Table zabbix.history-uint doesnt exist
  6. 2008年度回顾:决胜路由应用时代
  7. Android Studio常用快捷键
  8. matlab 点云根据法向量投影到六个平面
  9. android单元测试教程,Android单元测试-Junit
  10. 低版本android无法连接iPhone手机个人热点问题