是一种设计原则,降低程序代码之间的耦合度
对象由Ioc容器统一管理,当程序需要使用对象时直接从IoC容器中获取。这样对象的控制权就从应用程序转移到了IoC容器
依赖注入是一种消除类之间依赖关系的设计模式。例如,A类要依赖B类,A类不再直接创建B类,而是把这种依赖关系配置在外部xml文件(或java config文件)中,然后由Spring容器根据配置信息创建、管理bean类。可以简单的理解为给对象赋值
两种实现方式:
Spring容器调用构造方法注入被依赖的实例,构造方法可以是有参的或者是无参的。Spring在读取配置信息后,会通过反射方式调用实例的构造方法,如果是有参构造方法,可以在构造方法中传入所需的参数值,最后创建类对象。
步骤:
编写用户类User类,在User类中定义id、name和password三个属性
创建applicationContext-User.xml文件,在该文件中添加User类的配置信息
编写测试类:创建测试类TestUser,用于测试依赖注入的结果
- public class User {
- private int id; private String name; private String password;
- public User(int id, String name, String password){
- this.id=id; this.name=name; this.password=password; }
- public String toString(){
- return "id="+id+",name="+name+",password="+password; }}
具体介绍如下:
一个
例如:
public class TestUser {
public static void main(String[] args)throws Exception{
//加载applicationContext.xml配置
ApplicationContext applicationContext=new
ClassPathXmlApplicationContext("applicationContext-User.xml");
//获取配置中的User实例
User user=( User)applicationContext.getBean("user");
System.out.println(user);
}
}
步骤
编写用户类User类,在User类中定义id、name和password三个属性并且注明setter方法
创建applicationContext-User.xml文件,在该文件中添加User类的配置信息
编写测试类:创建测试类TestUser,用于测试依赖注入的结果
- public class User {
- private int id;
- private String name;
- private String password;
- public void setId(Integer id){
- this.id=id;
- }
- public void setUsername(String username){
- this.username= username;
- }
- public void setPassword (String password){
- this. password = password;
- }
- public String toString(){
- return "id="+id+",name="+name+",password="+password; }
- }
- <bean id="user" class="com.itheima.User">
- <property name="id" value="2">property>
- <property name="name" value="李四">property>
- <property name="password" value="456">property>
- bean>
property属性使用
name的属性值准确的讲不是属性名,而是set方法去掉set关键字后的名字
属性名idàsetter方法setIdd();去掉关键字setà即idd(驼峰命名)
- public class TestUser {
-
- public static void main(String[] args)throws Exception{
-
- //加载applicationContext.xml配置
-
- ApplicationContext applicationContext=new
-
- ClassPathXmlApplicationContext("applicationContext-User.xml");
-
- //获取配置中的User实例
-
- User user=( User)applicationContext.getBean("user");
-
- System.out.println(user);
-
- }
-
- }
依赖注入(DI)和控制反转(IoC)是从不同角度来描述了同一件事情。
依赖注入是从应用程序的角度描述,即应用程序依赖IoC容器创建并注入它所需要的外部资源;而控制反转是从IoC容器的角度描述,即IoC容器控制应用程序,由IoC容器反向地向应用程序注入应用程序所需要的外部资源。这里所说的外部资源可以是外部实例对象,也可以是外部文件对象等。
- class Player{
-
- Weapon weapon;
-
- Player(){
-
- // 与 Sword类紧密耦合
-
- this.weapon = new Sword();
-
- }
-
- public void attack() {
-
- weapon.attack();
- }
-
- }
这个方法存在耦合太紧的问题,例如,玩家的武器只能是剑Sword,而不能把Sword替换成枪Gun。要把Sword改为Gun,所有涉及到的代码都要修改,当然在代码规模小的时候这根本就不是什么问题,但代码规模很大时,就会费时费力了。
- class Player{
- Weapon weapon;
- // weapon 被注入进来
-
- Player(Weapon weapon){
- this.weapon = weapon;
- }
-
- public void attack() {
-
- weapon.attack();
-
- }
- public void setWeapon(Weapon weapon){
-
- this.weapon = weapon;
- }
- }
如上所示,Weapon类的实例并不在代码中创建,而是外部通过构造函数传入,传入类型是父类Weapon,所以传入的对象类型可以是任何Weapon子类。
传入哪个子类,可以在外部xml文件(或者java config文件)中配置,Spring容器根据配置信息创建所需子类实例,并注入Player类中,如下所示:
- <bean id="player" class="com.Springyx.demo.Player">
-
- <construct-arg ref="weapon"/>
-
- bean>
-
-
-
- <bean id="weapon" class=" com.Springyx.demo.Gun">
-
- bean>
上面代码中
只需修改这一处配置就可以。
注意:松耦合,并不是不要耦合。A类依赖B类,A类和B类之间存在紧密耦合,如果把依赖关系变为A类依赖B的父类B0类,在A类与B0类的依赖关系下,A类可使用B0类的任意子类,A类与B0类的子类之间的依赖关系是松耦合的(即创建中间商)