目录

一、 IoC

二、容器实现依赖注入

注解的原理:


一、 IoC

IoC:控制反转:某一接口实现类的选择控制权从调用类中移除,转交给第三方决定,即由Spring容器借由Bean配置来进行控制。eg:由导演控制剧本、角色和演员的依赖关系,将剧本对演员的依赖解耦。

那么通过控制反转(IOC)是怎么实现减少耦合的呢?总结网上的说法,从两个角度出发

1、控制反转

① 软件系统在没有引入IoC容器之前,对象A依赖对象B,那么A对象在实例化或者运行到某一点的时候,自己必须主动创建对象B或者使用已经创建好的对象B,其中不管是创建还是使用已创建的对象B,控制权都在我们自己手上。

② 如果软件系统引入了Ioc容器之后,对象A和对象B之间失去了直接联系,所以,当对象A实例化和运行时,如果需要对象B的话,IoC容器会主动创建一个对象B注入到对象A所需要的地方。

③ 通过前面①②的对比,可以看到对象A获得依赖对象B的过程,由主动行为变成了被动行为,即把创建对象交给了IoC容器处理,控制权颠倒过来了,这就是控制反转的由来!

注:在控制反转与解耦过程中使用了设计模式中的工厂模式。

工厂模式

工厂模式是指当应用程序中甲组件需要乙组件协助时,并不是在甲组件中直接实例化乙组件对象,而是通过乙组件的工厂获取,即该工厂可以生成某一类型组件的实例对象。在这种模式下,甲组件无需与乙组件以硬编码的方式耦合在一起,而只需与乙组件的工厂耦合,那么这样的话,通过依赖注入就可以完全不用关心对象的生命周期,什么时候被创建,什么时候销毁,只需直接使用即可,对象的生命周期由提供依赖注入的框架来管理,从而,让使用框架者,可以将重心完全放到业务逻辑处理的开发上。

2、spring之aop

① 在业务系统里除了要实现业务功能之外,还要实现如权限拦截、性能监控、事务管理等非业务功能。
通常的作法是非业务的代码穿插在业务代码中,从而导致了业务组件与非业务组件的耦合。

② aop面向切面编程,就是将这些分散在各个业务逻辑代码中的非业务代码,通过横向切割的方式抽取到一个独立的模块中,从而实现业务组件与非业务组件的解耦。

IoC通过DI(依赖注入)实现:让调用类对某一接口实现类的依赖关系由第三方(容器或协助类)注入,以移除调用类对实现类的依赖。

注入方法:

1.构造函数注入。 将接口实现类通过调用类的构造函数的参数传入。

public class MovieLister {private MovieFinder finder;public MovieLister(MovieFinder finder) {this.finder = finder;}...
}

2.属性注入。 (演员不是每场戏都要出现,在需要的时候出现即可)通过Setter方法传入。

public class MovieLister {s...public void setFinder(MovieFinder finder) {this.finder = finder;}
}

3.通过接口注入。 需要额外的接口声明而且和属性注入无本质区别,不提倡。

public interface InjectFinder {void injectFinder(MovieFinder finder);
}class MovieLister implements InjectFinder {...public void injectFinder(MovieFinder finder) {this.finder = finder;}...
}

二、容器实现依赖注入

Spring通过配置文件或注解描述类与类之间的依赖关系,自动完成类的初始化和依赖注入。

通过注解注入bean,就是实例化依赖类的方式,这也是为什么要将@Service和@Repository放到实现类上面而不是接口类上面,接口只是一个规范,需要各种实现类去实现这个接口,我们要用的就是这些实用类的方法。

注入的方式有@Recource和@Autowired

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。

@Resource有两个属性是比较重要的,分别是name和type,spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

@Resource装配顺序

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
  2. 如果指定了name,则从上下文中查找名称(id匹配的bean进行装配,找不到则抛出异常。
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配,如果没有匹配,则回退为一个原始类型(UserDao)进行匹配,如果匹配则自动装配。

当指定了@service的name值时, 在@Resource中要么不指示,如果指示的话,则要与之相对应。

当没有指定@service的name值是,在@Resource中随意。但是前提是,实现该接口的只有这一个类。

所以,建议是最好在@service和@Resoure中同时指定名称,并且做到一一对应。

如果采用@Autowired来注解,则同样无需指定name属性,若是实现该接口有多个类,则需要通过@Qualifier来做区分

注解的原理:

对于注解Test,如下,如果对AnnotationTest类进行注解,则运行时可以通过AnnotationTest.class.getAnnotation(Test.class)获取注解声明的值,从上面的句子就可以看出,它是从class结构中获取出Test注解的,所以肯定是在某个时候注解被加入到class结构中去了。

@Test("test")
public class AnnotationTest {public void test(){}
}

从java源码到class字节码是由编译器完成的,编译器会对java源码进行解析并生成class文件,而注解也是在编译时由编译器进行处理,编译器会对注解符号处理并附加到class结构中,根据jvm规范,class文件结构是严格有序的格式,唯一可以附加信息到class结构中的方式就是保存到class结构的attributes属性中。我们知道对于类、字段、方法,在class结构中都有自己特定的表结构,而且各自都有自己的属性,而对于注解,作用的范围也可以不同,可以作用在类上,也可以作用在字段或方法上,这时编译器会对应将注解信息存放到类、字段、方法自己的属性上。

在我们的AnnotationTest类被编译后,在对应的AnnotationTest.class文件中会包含一个RuntimeVisibleAnnotations属性,由于这个注解是作用在类上,所以此属性被添加到类的属性集上。即Test注解的键值对value=test会被记录起来。而当JVM加载AnnotationTest.class文件字节码时,就会将RuntimeVisibleAnnotations属性值保存到AnnotationTest的Class对象中,于是就可以通过AnnotationTest.class.getAnnotation(Test.class)获取到Test注解对象,进而再通过Test注解对象获取到Test里面的属性值。

注解被编译后的本质就是一个继承Annotation接口的接口,所以@Test其实就是“public interface Test extends Annotation”,当我们通过AnnotationTest.class.getAnnotation(Test.class)调用时,JDK会通过动态代理生成一个实现了Test接口的对象,并把将RuntimeVisibleAnnotations属性值设置进此对象中,此对象即为Test注解对象,通过它的value()方法就可以获取到注解值。

参考:

https://blog.csdn.net/qq_35923749/article/details/77159213

https://www.jb51.net/article/125696.htm

spring中注解及原理相关推荐

  1. Spring中注解大全

    Spring中注解大全 @Controller 标识一个该类是Spring MVC controller 处理器,用来创建处理http请求的对象 @Controller public class Te ...

  2. spring系列-注解驱动原理及源码-AOP使用及源码解析

    目录 一.用注解方式开启AOP 1.实例 2.AOP简单小结 二.AOP原理 1.@EnableAspectJAutoProxy溯源 2.AnnotationAwareAspectJAutoProxy ...

  3. spring系列-注解驱动原理及源码-声明式事务使用及原理解析

    目录 一.环境准备 1.JdbcTemplate使用实例 2.事务添加 二.声明式事务源码分析 1.原理(与AOP非常相似) 一.环境准备 1.JdbcTemplate使用实例 (1)pom文件添加依 ...

  4. spring系列-注解驱动原理及源码-自动装配

    目录 一.spring规范的bean自动注入 1.使用@Autowired自动注入 2.使用@Qualifier指定需要装配的组件 3.使用@Autowired装配null对象 4.使用@Primar ...

  5. spring系列-注解驱动原理及源码-bean生命周期

    目录 一.Bean的初始化和销毁 1.@Bean指定初始化和销毁方法 2.通过实现InitializingBean和Disposabean来初始化和销毁bean 3.使用JSR250定义的@PostC ...

  6. spring系列-注解驱动原理及源码-bean组件注册

    目录 一.环境初始化 1.环境准备 二.bean的手动注入 1.xml方式注入bean 2.使用@Configuration&@Bean方式注入bean 三.自动扫描注册组件及bean 1.使 ...

  7. Spring中注解大全和应用

    点击上方△蓝字关注我们 带你征服编程和泡妞两座大山 @Controller @RestController: @Service @Autowired @RequestMapping @RequestP ...

  8. spring中注解的通俗解释

    我们在没有用注解写spring配置文件的时候,会在spring配置文件中定义Dao层的bean,这样我们在service层中,写setDao方法,就可以直接通过接口调用Dao层,用了注解写法后,在配置 ...

  9. Spring中注解注入bean和配置文件注入bean

    注解的方式确实比手动写xml文件注入要方便快捷很多,省去了很多不必要的时间去写xml文件 按以往要注入bean的时候,需要去配置一个xml,当然也可以直接扫描包体,用xml注入bean有以下方法: 1 ...

  10. 深入理解spring中的AOP原理——实现MethodInterceptor接口,自已动手写一个AOP

    1.前言 AOP是面向切面编程,即"Aspect Oriented Programming"的缩写.面对切面,就是面向我们的关注面,不能让非关注面影响到我们的关注面.而现实中非关切 ...

最新文章

  1. C/C++:多个.cpp文件包括同一个.h头文件定义方法
  2. python dlib学习(十一):眨眼检测
  3. HOW TO WRITE A DAILY LAB NOTE?
  4. 90 % 的 Python 开发者不知道的描述符应用
  5. Docker + Jenkins 快速打造 PHP 持续集成服务器
  6. 多线程顺序交替打印ABCD
  7. 一点等于多少厘米_马桶知识介绍,你了解马桶多少
  8. Jmeter接口测试---加解密
  9. 摇号系统怎么做_雨水收集系统怎么做
  10. linux uuid挂载磁盘_linux下mount硬盘步骤,含UUID mount办法
  11. linux下qt实现vlc视频播放器,Qt编写视频播放器(vlc内核)
  12. 2020年低压电工考试试卷及低压电工复审考试
  13. bootbox.js——弹框插件
  14. 个人或公司微信公众号迁移转让流程,公证需要资料,订阅号服务号转移教程,怎么迁移
  15. PS常用的快捷键,PS快捷键大全
  16. 高通量测序领域常用名词解释
  17. Qt报错Parse error at “IID“的解决办法
  18. 小米 linux 内核面试,编译适配小米2S的CM Linux内核源代码及问题解决
  19. SDN学习路径——SDN架构
  20. 老旧小区安防难题成遗留“沉疴” 如何破解?

热门文章

  1. 自然语言处理之文本分类
  2. 软考中级软件设计师该怎么备考
  3. 植被抽稀lisp程序_地形图缩编中植被符号抽稀方法.doc
  4. windowspythonpygame安装_pygame安装(windows pycharm)
  5. Java实现随机抽奖
  6. 不需要appuploader破解版,也能上架
  7. Vue.js+axios制作的仿酷狗音乐-音乐播放界面
  8. [指导]HP ProBook/EliteBook/Zbook系列笔记本clover安装黑苹果
  9. 微信小程序开发工具格式化代码快捷键以及更改快捷键
  10. win10PPT不支持Flash动画