文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring之DI深入理解

2024-04-02 19:55

关注

本篇内容主要讲解“Spring之DI深入理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring之DI深入理解”吧!

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是通过反射技术实现注入的,它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性。

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

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

Setter注入

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

代码如下:

  1. public class Address { 

  2.     private String address; 

  3.     public String getAddress() { 

  4.         return address; 

  5.     } 

  6.     public void setAddress(String address) { 

  7.         this.address = address; 

  8.     } 


import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class Student {     private String name;     private Address address;     private String[] books;     private List<String> hobbys;     private Map<String,String> card;     private Set<String> games;     private String wife;     private Properties info;     public void setName(String name) {         this.name = name;     }     public String getName() {        return this.name;     }     public void setAddress(Address address) {         this.address = address;     }    public void setBooks(String[] books) {         this.books = books;     }     public void setHobbys(List<String> hobbys) {         this.hobbys = hobbys;     }     public void setCard(Map<String, String> card) {         this.card = card;     }     public void setGames(Set<String> games) {         this.games = games;     }     public void setWife(String wife) {         this.wife = wife;     }     public void setInfo(Properties info) {         this.info = info;     }     public void show(){         System.out.println("name="+ name                 +",address="+ address.getAddress()                 +",books="         );         for (String book:books){             System.out.print("<<"+book+">>\t");         }         System.out.println("\nhobbys:"+hobbys);         System.out.println("card:"+card);         System.out.println("games:"+games);         System.out.println("wife:"+wife);         System.out.println("info:"+info);     } }

配置文件

<bean id="student" class="com.my.demo.Student">      <property name="name" value="小明"/>  </bean>

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

测试类

public static void main(String[] args) {            ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");            Student student=(Student)context.getBean("student");            System.out.println(student.getName());         }

运行结果,输出:小明

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

bean注入

使用ref进行引入其他bean

<bean id="student" class="com.my.demo.Student">      <property name="name" value="小明"/>     <property name="address" ref="addr"/> </bean>

数组注入

<property name="books">          <array>              <value>数学</value>              <value>语文</value>              <value>英语</value>          </array>     </property>

List注入

<property name="hobbys">      <list>          <value>听歌</value>          <value>看电影</value>          <value>打游戏</value>      </list>   </property>

Map注入

<property name="card">      <map>          <entry key="招行" value="123456789"/>          <entry key="工行" value="987654321"/>      </map>  </property>

set注入

<property name="games">      <set>          <value>CS</value>          <value>斗地主</value>          <value>消消乐</value>      </set>  </property>

Null注入

<property name="wife"><null/></property>

Properties注入

<propertyname="info">      <props>          <propkey="学号">123456</prop>          <propkey="性别">男</prop>          <propkey="姓名">小明</prop>      </props>  </property>

测试方法

public static void main(String[] args) {            ApplicationContextcontext = new ClassPathXmlApplicationContext("bean1.xml");            Studentstudent=(Student)context.getBean("student");            student.show();          }

运行结果,输出:

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

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

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

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

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

wife:null

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

构造器注入

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

代码如下:

public class Student2{        private String name;        public Student2(String name) {           this.name = name;       }        public void setName(String name) {           this.name = name;       }        public void show(){           System.out.println("name="+ name );       }     }

配置文件中设置

 <!-- 第一种根据index参数下标设置 --> <bean id="student1" class="com.my.demo.Student2">    <!-- index是构造方法 , 下标从0开始 -->    <constructor-arg index="0" value="kevin1"/> </bean> <!--第二种根据参数名字设置 --> <bean id="student2" class="com.my.demo.Student2">    <!-- name指参数名 -->    <constructor-arg name="name" value="kevin2"/> </bean> <!--第三种根据参数类型设置(不推荐使用) --> <bean id="student3" class="com.my.demo.Student2">    <constructor-arg type="java.lang.String" value="kevin3"/> </bean>

测试代码

public static void main(String[] args) {            ApplicationContextcontext = new ClassPathXmlApplicationContext("bean3.xml");                   Student2 user = (Student2) context.getBean("student1")            user.show();         }

运行结果:

name=kevin1

参数直接注入

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

@Autowired

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

需要导入 spring-aop的包

配置文件中设置<

context:annotation-config/>

代码:

public class Animal {    @Autowired    private Cat cat; //运行时spring通过DI会把Cat类实例化    @Autowired private Dog dog;//运行时spring通过DI会把Dog类实例化           public void printCatshot() {               cat.shout();        }           public void printDogshot() {                 dog.shout(); } }

 @Qualifier

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

代码:

@Autowired @Qualifier(value= "dog1") private Dog dog1; beans.xml <bean id="dog1" class="com.my.demo.Dog"/> <bean id="dog2" class=" com.my.demo.Dog"/>

 @Resource

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

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

代码

@Resource(name = "dog2") private Dog dog; beans.xml <bean id="dog1" class=" com.my.demo.Dog "/> <bean id="dog2" class="com.my.demo.Dog "/>

 最简单的解释

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

到此,相信大家对“Spring之DI深入理解”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯