- IOC概述
IOC 是Inverse of Control(控制反转)的缩写,反转的是对象的控制权(new)。最初学习java的时候,我们都是在一个对象中通过new的方式,来创建一个对象。例如如下场景:演员获得电影信息
public class Actor {
public void action(){
Movie movie = new Movie();
movie.getMovieInfo();
}
}
public class Movie {
public void getMovieInfo(){
System.out.println("movie name is ...,dirctoried by ...");
}
}
以往的做法,如果我们Actor 要操作Movie的方法,那么必须在Actor 中new一个Movie的对象。
通过IOC的话,我们要如何实现呢?我们可以借助导演的角色,作为第三方的代理控制者。场景依旧如下:导演通知演员电影信息
public class Director {
//控制Actor
Actor actor = new Actor();
//控制Movie
Movie movie = new Movie();
public void informActor(){
actor.setMovie(movie);
actor.action();
}
}
public class Actor {
//Movie作为Actor的成员,由Director分配
Movie movie;
public void action(){
movie.getMovieInfo();
}
//注入Movie属性
public void setMovie(Movie movie){
this.movie = movie;
}
}
public class Movie {
public void getMovieInfo(){
System.out.println("movie name is ...,dirctoried by ...");
}
}
通过Dircetor的角色,把Actor的Movie控制权反转到了Dircetor上面,Actor不需要自己new一个Movie,而是把Movie作为一个自身的成员,由Director通过set访问点把new好的Movie传入。这样就达到了释放控制权,解耦关系的作用。Director就相当于一个大管家,Actor需要的,Director会主动分配给Actor,这个就是控制反转的精髓所在。而在Spring中,Spring容器正是通过这种大管家的身份,给每个Bean分配他们所需要的资源的。
所以,IOC其实是一种思想,通过转交控制权托管给第三方,来简化自身的操作。而Spring把资源分配权转交给容器,然后每个角色只关注自己的action。所以Spring的核心是IOC,Spring中核心的角色是BeanFactory(Context)。
上面加粗的部分,其实说明了在Spring中IOC的一种方式,通过setter来进行属性注入。因为IOC的概念有些难理解,所以泰斗级的人物Martin Fowler提出了DI(Dependency Injection)依赖注入的概念来代替IOC,让调用者对某一接口的实现依赖关系由第三方注入,以移除调用类对某一接口的依赖。那么当然,依赖的接口,这时候也会作为一个属性被注入到调用类中。
既然Spring中有了DI的概念,就知道了,需要注入的是属性,那么被调用类也就成为了Bean,Bean中有属性,有构造法方法,所以,每个Spring容器管理的对象,都可以作为Bean来对待。DI的思想,成了Spring IOC的核心,而Bean,无疑是Spring中最重要的角色了。
那么下面,也就不难理解Spring会有下面几种IOC的实现方式了。
Spring的IOC实现方式
1.构造函数注入
2.属性注入(setter注入)
3.接口注入(工厂方法)- 构造参数注入:通过调用类的构造方法,把属性通过构造函数变量传入
public class MoAttack{
private GeLi geli;
public MoAttack(GeLi geli) {
this.geli = geli;
}
public void cityGateAsk() {
geli.responseAsk("墨者革离");
}
}
public interface GeLi {
void responseAsk(String saying);
}
public class Director {
public void direct(){
GeLi geli = (GeLi) new LiuDeHua();
MoAttack moAttack = new MoAttack(geli);
moAttack.cityGateAsk();
}
}
- 属性注入:通过setter方式把属性注入
public class MoAttack {
private GeLi geli;
public void setGeli(GeLi geli) {
this.geli = geli;
}
public void cityGateAsk() {
geli.responseAsk("墨者革离");
}
}
public interface GeLi {
void responseAsk(String saying);
}
public class Director {
public void direct(){
GeLi geli = (GeLi) new LiuDeHua();
MoAttack moAttack = new MoAttack();
moAttack.setGeli(geli);
moAttack.cityGateAsk();
}
}
- 接口注入
public class MoAttack implements ActorArrangable {
private GeLi geli;
//实现接口方法
public void injectGeli(GeLi geli) {
this.geli = geli;
}
public void cityGateAsk() {
geli.responseAsk("墨者革离");
}
}
public interface ActorArrangable {
void injectGeli(GeLi geli);
}
public interface GeLi {
void responseAsk(String saying);
}
public class Director {
public void direct(){
GeLi geli = new LiuDeHua();
MoAttack moAttack = new MoAttack();
moAttack.injectGeli(geli);
moAttack.cityGateAsk();
}
}
以上大致浏览下各种注入方式,进一步说民,DI或者是IOC只是一种思想。通过不同的方式,可以达到同一个效果。但是有个问题,我们虽然对MoAttack 进行了注入,但是是通过Director实例进行的。如果我现在想换个导演,让导演,剧本,和演员都解耦,我是不是还得再找一个托管的类?在Spring中,早已经把所有的注入类看做是一个Bean,Spring通过容器作为其他所有Bean的大管家,对其他Bean进行依赖注入。只需要通过简单的xml配置或者是注解配置,就可以建立Bean之间的关系。通过new XmlBeanFactory(“beans.xml”)或者是new ApplicationContext(“beans.xml”)等方式,即可启动Spring容器,容器会返回就绪的Bean。
那么Spring又是通过什么方式来进行DI的呢?这个就要归功于Java的反射,反射则是Spring IOC的核心。
以上就是IOC和SpringIOC的简介部分,至于Spring是用什么方式,以及Spring中如何通过IOC装配Bean,后面会有详解。