欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring的核心机制:依赖注入

程序员文章站 2022-06-22 12:45:40
依赖注入的概念 当一个对象要调用另一个对象时,一般是new一个被调用的对象,示例: class A{ private B b=new B(); public void test(){ b.say(); } } A类的对象依赖于B类对象,如果没有B类对象,A类对象就不能正常工作,称A依赖于B。 以上方 ......

 

依赖注入的概念

当一个对象要调用另一个对象时,一般是new一个被调用的对象,示例:

class  a{

  private b b=new b();

  public  void  test(){

    b.say();

  }

}

a类的对象依赖于b类对象,如果没有b类对象,a类对象就不能正常工作,称a依赖于b。

以上方式会增加类a与类b的耦合性,不利于项目后期的升级(扩展)、维护。

 

在spring中,b类的实例(被调用者),不再由a类(调用者)创建,而是由spring容器创建,创建好以后,由spring容器将b类的实例注入a类对象中,称为依赖注入(dependency injection,di)。

原本是由a类主动创建b类对象(a类控制b类的创建),现在是spring容器创建b类对象,注入a类对象中,a类被动接受spring容器创建的b类实例,b类对象创建的控制权发生了反转,所以又叫做控制反转(inversion of control,ioc)。

 

依赖注入是一种优秀的解耦方式,由spring容器负责控制类(bean)之间的关系,降低了类之间的耦合。

因为spring容器负责依赖注入(ioc),所以spring容器也被称为spring ioc容器。

 

依赖注入有2种实现方式:

  • 设值注入
  • 构造注入

 

 

 

 

设值注入

通过主调类的setter()方法注入被调类的实例。一个参数即一个依赖对象。

 

1、分别写2个接口

1 public interface student {
2     public string getname();
3 }
1 public interface teacher {
2     public void say();
3 }

 

 

2、分别写2个实现类

 1 public class badstudent implements student {
 2     private string name;
 3 
 4     public badstudent(string name){
 5         this.name=name;
 6     }
 7 
 8     @override
 9     public string getname(){
10         return name;
11     }
12 }
 1 public class mathteacher implements teacher{
 2     private student student;
 3 
 4     //主调者的setter()方法,接受被调者实例
 5     public void setstudent(student student){
 6         this.student=student;
 7     }
 8 
 9     @override
10     public void say() {
11         system.out.println(student.getname()+",叫家长来一下。");
12     }
13 }

 类与接口耦合。

 

 

3、在applicationcontext.xml文件中配置bean

1 <!-- 初始化badstudent类的实例lisi-->
2     <bean name="lisi" class="beans.badstudent">
3         <constructor-arg value="李四" />  <!--向badstudent的构造函数传递”李四“-->
4     </bean>
5 
6     <!--配置依赖-->
7     <bean name="mathteacher" class="beans.mathteacher">
8         <property name="student" ref="lisi" />  <!--name指定setter方法的形参,ref或者value指定实参:某个bean的name-->
9     </bean>

 

 <constructor-arg>元素向该bean的构造函数传递实参,一个<constructor-arg>传递一个实参,一个<bean>可配置多个<constructor-arg>,根据传递的实参个数来调用相应的构造函数。constructor-arg即构造器参数。

实参值通过value或ref属性来指定。value指定的是java基础类型的参数,ref即reference(引用),指定依赖的其它bean。

可通过属性index指定该value是第几个参数,默认从0自动递增。

 

 

<property>属性指定setter方法的实参。一个<property>指定一个参数,一个<bean>可带有多个<property>子元素。

name属性指定setter方法中的某个形参,实参由value或ref指定。

如果实参是某个bean的实例,用ref指定,值是该bean的name属性值。

如果实参是java的基础类型(整型、浮点型、string等),用value指定(放在引号中),spring容器会自动根据name的指定形参的类型,将实参转换为相应的类型进行赋值。

 

 

4、写一个测试类

1 public class test {
2     public static void main(string[] args) {
3         classpathxmlapplicationcontext applicationcontext=new classpathxmlapplicationcontext("applicationcontext.xml");
4         mathteacher mathteacher=applicationcontext.getbean("mathteacher",mathteacher.class);
5         mathteacher.say();
6     }
7 }

 看到控制台已经打印出了“李四,叫家长来一下。”。

 

 

 

 

 

构造注入

通过构造函数注入。

1、上面的代码,将mathteacher类修改如下

 1 public class mathteacher implements teacher{
 2     private student student;
 3 
 4     //主调者的构造方法
 5     public mathteacher(student student){
 6         this.student=student;
 7     }
 8 
 9     @override
10     public void say() {
11         system.out.println(student.getname()+",叫家长来一下。");
12     }
13 }

不使用setter方法注入依赖的对象,而是使用构造函数注入依赖的对象。

 

2、修改spring容器的配置如下

1  <!-- 初始化badstudent类的实例lisi-->
2     <bean name="lisi" class="beans.badstudent">
3         <constructor-arg value="李四" />
4     </bean>
5 
6     <!--配置依赖-->
7     <bean name="mathteacher" class="beans.mathteacher">
8         <constructor-arg name="student" ref="lisi" />
9     </bean>

 

3、运行,看到控制台打印出“李四,叫家长来一下。”。

 

 

 

说明

  • 这两种方式都可以注入java的自带的数据类型。
  • value是注入java的基础类型,ref是注入依赖的bean。当然也可以用<value>、<ref>子元素的形式配置。