测试同学上手Spring 之DI深入解析

2025-05-29 0 75

测试同学上手Spring 之DI深入解析

前面已经介绍了如何上手Spirng编码以及IOC的核心概念,今天给大家讲解Spring的另一个重点——DI

测试同学上手Spring 之DI深入解析

Spring核心模块

DI概念

IoC 其实有两种方式,一种就是 DI(Dependency Injection) ,而另一种是 DL(Dependency Lookup)即依赖查找。前者是当前组件被动接受IoC容器注入的依赖组件,而后者则是组件主动去某个服务注册地查找其依赖的组件,我们这里重点介绍DI

IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。Spring是通过反射技术实现注入的,它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性。

简单的总结一下依赖注入:

  • 依赖 : 指Bean对象的创建依赖于容器 。
  • 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配。

注入的方式主要包括Setter注入(重点)、构造器注入和参数直接注入。还有拓展方式注入,即:p命名空间注入和c命名空间注入,这里就不再展开介绍了,有兴趣的同学可以自行研究。

Setter注入

IoC 容器使用 setter 方法注入被依赖的实例。通过调用无参构造器或无参 static 工厂方法实例化 bean 后,调用该 bean的setter 方法(类中必须有属性的set方法),即可实现基于setter的DI

代码如下:

  1. publicclassAddress{
  2. privateStringaddress;
  3. publicStringgetAddress(){
  4. returnaddress;
  5. }
  6. publicvoidsetAddress(Stringaddress){
  7. this.address=address;
  8. }
  9. }

  1. importjava.util.List;
  2. importjava.util.Map;
  3. importjava.util.Properties;
  4. importjava.util.Set;
  5. publicclassStudent{
  6. privateStringname;
  7. privateAddressaddress;
  8. privateString[]books;
  9. privateList<String>hobbys;
  10. privateMap<String,String>card;
  11. privateSet<String>games;
  12. privateStringwife;
  13. privatePropertiesinfo;
  14. publicvoidsetName(Stringname){
  15. this.name=name;
  16. }
  17. publicStringgetName(){
  18. returnthis.name;
  19. }
  20. publicvoidsetAddress(Addressaddress){
  21. this.address=address;
  22. }
  23. publicvoidsetBooks(String[]books){
  24. this.books=books;
  25. }
  26. publicvoidsetHobbys(List<String>hobbys){
  27. this.hobbys=hobbys;
  28. }
  29. publicvoidsetCard(Map<String,String>card){
  30. this.card=card;
  31. }
  32. publicvoidsetGames(Set<String>games){
  33. this.games=games;
  34. }
  35. publicvoidsetWife(Stringwife){
  36. this.wife=wife;
  37. }
  38. publicvoidsetInfo(Propertiesinfo){
  39. this.info=info;
  40. }
  41. publicvoidshow(){
  42. System.out.println("name="+name
  43. +",address="+address.getAddress()
  44. +",books="
  45. );
  46. for(Stringbook:books){
  47. System.out.print("<<"+book+">>\\t");
  48. }
  49. System.out.println("\\nhobbys:"+hobbys);
  50. System.out.println("card:"+card);
  51. System.out.println("games:"+games);
  52. System.out.println("wife:"+wife);
  53. System.out.println("info:"+info);
  54. }
  55. }

配置文件

  1. <beanid="student"class="com.my.demo.Student">
  2. <propertyname="name"value="小明"/>
  3. </bean>

配置文件中把name 赋值为小明,即完成了对代码 private String name的注入。

测试类

  1. publicstaticvoidmain(String[]args){
  2. ApplicationContextcontext=newClassPathXmlApplicationContext("bean1.xml");
  3. Studentstudent=(Student)context.getBean("student");
  4. System.out.println(student.getName());
  5. }

运行结果,输出:小明

常见注入方式的xml 配置如下:

bean注入

使用ref进行引入其他bean

  1. <beanid="student"class="com.my.demo.Student">
  2. <propertyname="name"value="小明"/>
  3. <propertyname="address"ref="addr"/>
  4. </bean>

数组注入

  1. <propertyname="books">
  2. <array>
  3. <value>数学</value>
  4. <value>语文</value>
  5. <value>英语</value>
  6. </array>
  7. </property>

List注入

  1. <propertyname="hobbys">
  2. <list>
  3. <value>听歌</value>
  4. <value>看电影</value>
  5. <value>打游戏</value>
  6. </list>
  7. </property>

Map注入

  1. <propertyname="card">
  2. <map>
  3. <entrykey="招行"value="123456789"/>
  4. <entrykey="工行"value="987654321"/>
  5. </map>
  6. </property>

set注入

  1. <propertyname="games">
  2. <set>
  3. <value>CS</value>
  4. <value>斗地主</value>
  5. <value>消消乐</value>
  6. </set>
  7. </property>

Null注入

  1. <propertyname="wife"><null/></property>

Properties注入

  1. <propertyname="info">
  2. <props>
  3. <propkey="学号">123456</prop>
  4. <propkey="性别">男</prop>
  5. <propkey="姓名">小明</prop>
  6. </props>
  7. </property>

测试方法

  1. publicstaticvoidmain(String[]args){
  2. ApplicationContextcontext=newClassPathXmlApplicationContext("bean1.xml");
  3. Studentstudent=(Student)context.getBean("student");
  4. student.show();
  5. }

运行结果,输出:

name=小明,address=北京,books=

<<数学>> <<语文>> <<英语>>

hobbys:[听歌, 看电影, 打游戏]

card:{招行=123456789, 工行=987654321}

games:[CS, 斗地主, 消消乐]

wife:null

info:{学号=123456, 性别=男, 姓名=小明}

构造器注入

指IoC 容器使用构造方法注入被依赖的实例。基于构造器的 DI 通过调用带参数的构造方法实现,每个参数代表一个依赖。

代码如下:

  1. publicclassStudent2{
  2. privateStringname;
  3. publicStudent2(Stringname){
  4. this.name=name;
  5. }
  6. publicvoidsetName(Stringname){
  7. this.name=name;
  8. }
  9. publicvoidshow(){
  10. System.out.println("name="+name);
  11. }
  12. }

配置文件中设置

  1. <!–第一种根据index参数下标设置–>
  2. <beanid="student1"class="com.my.demo.Student2">
  3. <!–index是构造方法,下标从0开始–>
  4. <constructor-argindex="0"value="kevin1"/>
  5. </bean>
  6. <!–第二种根据参数名字设置–>
  7. <beanid="student2"class="com.my.demo.Student2">
  8. <!–name指参数名–>
  9. <constructor-argname="name"value="kevin2"/>
  10. </bean>
  11. <!–第三种根据参数类型设置(不推荐使用)–>
  12. <beanid="student3"class="com.my.demo.Student2">
  13. <constructor-argtype="java.lang.String"value="kevin3"/>
  14. </bean>

测试代码

  1. publicstaticvoidmain(String[]args){
  2. ApplicationContextcontext=newClassPathXmlApplicationContext("bean3.xml");
  3. Student2user=(Student2)context.getBean("student1")
  4. user.show();
  5. }

运行结果:

name=kevin1

参数直接注入

主要通过注解@Autowired、@Qualifier和@Resource来实现

@Autowired

@Autowired是按类型自动转配的,不支持id匹配。

需要导入 spring-aop的包

配置文件中设置<

context:annotation-config/>

代码:

  1. publicclassAnimal{
  2. @AutowiredprivateCatcat;//运行时spring通过DI会把Cat类实例化
  3. @AutowiredprivateDogdog;//运行时spring通过DI会把Dog类实例化
  4. publicvoidprintCatshot(){
  5. cat.shout();
  6. }
  7. publicvoidprintDogshot(){
  8. dog.shout();
  9. }
  10. }

@Qualifier

@Autowired是根据类型进行自动装配的。如果当Spring上下文中存在一个类型的不同bean时,就会抛出BeanCreationException异常;我们可以使用@Qualifier配合@Autowired来解决这些问题。

代码:

  1. @Autowired
  2. @Qualifier(value="dog1")
  3. privateDogdog1;
  4. beans.xml
  5. <beanid="dog1"class="com.my.demo.Dog"/>
  6. <beanid="dog2"class="com.my.demo.Dog"/>

@Resource

@Resource是J2EE提供的, 需导入Package: javax.annotation.Resource;

@Resource如有指定的name属性,先按该属性进行byName方式查找装配,其次再进行默认的byName方式进行装配,都不成功,则报异常。

代码

  1. @Resource(name="dog2")
  2. privateDogdog;
  3. beans.xml
  4. <beanid="dog1"class="com.my.demo.Dog"/>
  5. <beanid="dog2"class="com.my.demo.Dog"/>

最简单的解释

IoC通过DI技术主要实现了以下两点:

  • 在系统运行中,动态地向某个对象提供它所需要的其他对象;
  • 在系统运行中,动态地从配置文件中读取数据来为对象的属性进行赋值。

原文地址:https://www.toutiao.com/i6942279290830586399/

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 测试同学上手Spring 之DI深入解析 https://www.kuaiidc.com/112769.html

相关文章

发表评论
暂无评论