Spring学习笔记(1.1):什么是依赖注入,依赖注入的实现

这片文章是对自己学习的总结。


1、什么是依赖注入

简单回忆一下控制反转的概念(IOC)。

开发过程中,我们在一个类中的代码常常会依赖到其他的类对象。比如下面的service类需要用到dao类提供的操作数据库的方法,也就是service依赖dao。没有dao,service的一些方法就没法进行下去。

既然需要这个类对象,那最简单的方式就是直接去new出来。

public class ServiceImpl implements Service {
	public void insertData(String data) {
		//直接new
		Dao dao = new Dao();
		dao.insert(data);
	}
}

这里ServiceImpl和Dao产生了依赖关系,ServiceImpl依赖Dao。这种情况下,ServiceImpl需要Dao的时候,ServiceImpl是主动去创建一个dao对象(注意是主动创造)。

这种主动创建的行为会带来一些麻烦。因为代码已经写死了,A和B是直接耦合在一起的。如果以后因为业务需求,类B的创建出现了一些问题,比如无法直接new,构造器被隐藏设为私有。等业务人员改完B的代码,重新启动项目后发现A开始报错,又不得不去处理A的逻辑。看到了吧,我们只是想修改B的逻辑,但因为一些依赖关系又不得不去处理很多”原本不应该管的逻辑“。可以想象。这样的依赖关系如果多了的话,那后期维护代码会变得举步维艰。

仔细想想,A和B的依赖中,A只是想要B的服务。A其实不需要关系B的创建过程,只要有个B的对象来提供服务就好。

正是有了这个突破点,控制反转的概念顺势而出,即当类A与类B产生依赖关系时(A需要B),不需要A去主动创建B,而是交给外界创建好B对象,然后通过一些方式把B对象交给A使用。

控制反转的意思是将创建B这个行为的主动权从需要方类A的手中反转到其他人手中。

那外界创建好类B后,将B交给A的行为,就是依赖注入。也就是将A依赖的资源注入到A中。


2、依赖注入的三种方式

2.1 构造器注入

构造器中是可以传参的。以上面的例子为例,我们可以在ServiceImpl中设置一个私有的,类型为Dao的变量。然后ServiceImpl的构造器中传入Dao类型的参数,在构造方法中将传进来的参数赋值给ServiceImpl的私有变量。然后ServiceImpl就可以调用自己的私有变量的方法享受Dao对象提供的服务。

public class ServiceImpl implements Service {
	//声明自己的dao对象,等会在构造方法中这个变量赋值
	private Dao dao;

	public ServiceImpl(Dao dao){
		this.dao = dao;
	}
	public void insertData(String data) {
		//这时候dao对象就不是A主动创建的了,是外界创建好,然后在构造方法中注入给ServiceImpl的
		dao.insert(data);
	}
}

2.2 setter方法注入

与构造器类似,只是注入的时机不是在构造类时,而是构造好类ServiceImpl之后,使用setter方法将Dao对象赋值个ServiceImpl对象的私有成员。

public class ServiceImpl implements Service {
	//声明自己的dao对象,等会在构造方法中这个变量赋值
	private Dao dao;

	public setter(Dao dao) {
		this.dao = dao;
	}
	public void insertData(String data) {
		//这时候dao对象就不是A主动创建的了,是外界创建好,然后在构造方法中注入给ServiceImpl的
		dao.insert(data);
	}
}

2.3 接口注入

接口注入显得很繁琐。我自己感觉也很多此一举。这个方式是定义一个接口,接口中有个方法强制你必须实现一个依赖注入。这样就好像是使用setter方法注入,但是是强制你必须实现setter方法注入。

我们用代码来演示。Service接口中定义了一个inject()方法。这个方法告诉继承者们必须完成dao对象的注入。

public interface Service {
	private Dao dao;
	/**
	 * 这个方法用来给dao赋值
	 */
	public void inject(Dao dao)
}

public class ServiceImpl implements Service {
	@Override
	public void inject(Dao dao) {
		this.dao = dao;
	}
}

是不是多此一举?这个方法太繁琐,现在没什么人用了,只是在早起的Avalon的项目中使用。

你可能感兴趣的:(Spring)