当一个对象要调用另外一个对象时,通常是new一个被调用的对象,示例:app
class A{ide
private B b=new B();函数
public void test(){测试
b.say();this
}spa
}code
A类的对象依赖于B类对象,若是没有B类对象,A类对象就不能正常工做,称A依赖于B。xml
以上方式会增长类A与类B的耦合性,不利于项目后期的升级(扩展)、维护。对象
在Spring中,B类的实例(被调用者),再也不由A类(调用者)建立,而是由Spring容器建立,建立好之后,由Spring容器将B类的实例注入A类对象中,称为依赖注入(Dependency Injection,DI)。blog
本来是由A类主动建立B类对象(A类控制B类的建立),如今是Spring容器建立B类对象,注入A类对象中,A类被动接受Spring容器建立的B类实例,B类对象建立的控制权发生了反转,因此又叫作控制反转(Inversion of Control,IoC)。
依赖注入是一种优秀的解耦方式,由Spring容器负责控制类(Bean)之间的关系,下降了类之间的耦合。
由于Spring容器负责依赖注入(IoC),因此Spring容器也被称为Spring IoC容器。
依赖注入有2种实现方式:
经过主调类的setter()方法注入被调类的实例。一个参数即一个依赖对象。
一、分别写2个接口
1 public interface Student { 2 public String getName(); 3 }
1 public interface Teacher { 2 public void say(); 3 }
二、分别写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 }
类与接口耦合。
三、在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的指定形参的类型,将实参转换为相应的类型进行赋值。
四、写一个测试类
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 }
看到控制台已经打印出了“李四,叫家长来一下。”。
经过构造函数注入。
一、上面的代码,将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方法注入依赖的对象,而是使用构造函数注入依赖的对象。
二、修改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>
三、运行,看到控制台打印出“李四,叫家长来一下。”。
value是注入Java的基础类型,ref是注入依赖的Bean。固然也能够用<value>、<ref>子元素的形式配置。