spring中注解及原理
目录
一、 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装配顺序
- 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
- 如果指定了name,则从上下文中查找名称(id匹配的bean进行装配,找不到则抛出异常。
- 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。
- 如果既没有指定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中注解及原理相关推荐
- Spring中注解大全
Spring中注解大全 @Controller 标识一个该类是Spring MVC controller 处理器,用来创建处理http请求的对象 @Controller public class Te ...
- spring系列-注解驱动原理及源码-AOP使用及源码解析
目录 一.用注解方式开启AOP 1.实例 2.AOP简单小结 二.AOP原理 1.@EnableAspectJAutoProxy溯源 2.AnnotationAwareAspectJAutoProxy ...
- spring系列-注解驱动原理及源码-声明式事务使用及原理解析
目录 一.环境准备 1.JdbcTemplate使用实例 2.事务添加 二.声明式事务源码分析 1.原理(与AOP非常相似) 一.环境准备 1.JdbcTemplate使用实例 (1)pom文件添加依 ...
- spring系列-注解驱动原理及源码-自动装配
目录 一.spring规范的bean自动注入 1.使用@Autowired自动注入 2.使用@Qualifier指定需要装配的组件 3.使用@Autowired装配null对象 4.使用@Primar ...
- spring系列-注解驱动原理及源码-bean生命周期
目录 一.Bean的初始化和销毁 1.@Bean指定初始化和销毁方法 2.通过实现InitializingBean和Disposabean来初始化和销毁bean 3.使用JSR250定义的@PostC ...
- spring系列-注解驱动原理及源码-bean组件注册
目录 一.环境初始化 1.环境准备 二.bean的手动注入 1.xml方式注入bean 2.使用@Configuration&@Bean方式注入bean 三.自动扫描注册组件及bean 1.使 ...
- Spring中注解大全和应用
点击上方△蓝字关注我们 带你征服编程和泡妞两座大山 @Controller @RestController: @Service @Autowired @RequestMapping @RequestP ...
- spring中注解的通俗解释
我们在没有用注解写spring配置文件的时候,会在spring配置文件中定义Dao层的bean,这样我们在service层中,写setDao方法,就可以直接通过接口调用Dao层,用了注解写法后,在配置 ...
- Spring中注解注入bean和配置文件注入bean
注解的方式确实比手动写xml文件注入要方便快捷很多,省去了很多不必要的时间去写xml文件 按以往要注入bean的时候,需要去配置一个xml,当然也可以直接扫描包体,用xml注入bean有以下方法: 1 ...
- 深入理解spring中的AOP原理——实现MethodInterceptor接口,自已动手写一个AOP
1.前言 AOP是面向切面编程,即"Aspect Oriented Programming"的缩写.面对切面,就是面向我们的关注面,不能让非关注面影响到我们的关注面.而现实中非关切 ...
最新文章
- C/C++:多个.cpp文件包括同一个.h头文件定义方法
- python dlib学习(十一):眨眼检测
- HOW TO WRITE A DAILY LAB NOTE?
- 90 % 的 Python 开发者不知道的描述符应用
- Docker + Jenkins 快速打造 PHP 持续集成服务器
- 多线程顺序交替打印ABCD
- 一点等于多少厘米_马桶知识介绍,你了解马桶多少
- Jmeter接口测试---加解密
- 摇号系统怎么做_雨水收集系统怎么做
- linux uuid挂载磁盘_linux下mount硬盘步骤,含UUID mount办法
- linux下qt实现vlc视频播放器,Qt编写视频播放器(vlc内核)
- 2020年低压电工考试试卷及低压电工复审考试
- bootbox.js——弹框插件
- 个人或公司微信公众号迁移转让流程,公证需要资料,订阅号服务号转移教程,怎么迁移
- PS常用的快捷键,PS快捷键大全
- 高通量测序领域常用名词解释
- Qt报错Parse error at “IID“的解决办法
- 小米 linux 内核面试,编译适配小米2S的CM Linux内核源代码及问题解决
- SDN学习路径——SDN架构
- 老旧小区安防难题成遗留“沉疴” 如何破解?
热门文章
- 自然语言处理之文本分类
- 软考中级软件设计师该怎么备考
- 植被抽稀lisp程序_地形图缩编中植被符号抽稀方法.doc
- windowspythonpygame安装_pygame安装(windows pycharm)
- Java实现随机抽奖
- 不需要appuploader破解版,也能上架
- Vue.js+axios制作的仿酷狗音乐-音乐播放界面
- [指导]HP ProBook/EliteBook/Zbook系列笔记本clover安装黑苹果
- 微信小程序开发工具格式化代码快捷键以及更改快捷键
- win10PPT不支持Flash动画