Spring IOC_01 IOC与DI好处

IOC与DI理解

IOC(Inversion Of Control):我的理解是在某个类(A)聚合另外一个类(B)的时候,由原本在当前类中去直接实例化这个类(类似privat B b = new C())变成由容器提供,按需分配。这样不必在当前类中强耦合C类,这样就可以在不改变原有代码的基础上增加实现类(D),大大提高了项目的扩展性。

DI(Dependency Injection):我的理解是IOC的一种实现方式,容器提供是由setter或者constructor来实现,通过这两种方式注入你依赖的实现类,降低了项目的耦合度,并提高了扩展性。

代码演示理解

A类:PersonService

public class PersonService {
    private PersonDao personDao = new PersonDaoOracleImpl();

    public Person getPerson() {
        return personDao.getPerson();
    }
}

B类:PersonDao

public interface PersonDao {
    Person getPerson();
}

C类:PersonDaoOracleImpl

public class PersonDaoOracleImpl implements PersonDao {
    @Override
    public Person getPerson() {
        return new Person(0, "Oracle", true);
    }
}

测试类

public class IocTest {
    public static void main(String[] args) {
        PersonService personService = new PersonService();
        System.out.println(personService.getPerson());
    }
}

输出结果:Person{id=0, name='Oracle', male=true}

在以上的例子中假设使用的是Oracle数据库,那么我现在想更换为Mysql数据库的话,是不是应当去修改PersonService中new PersonDaoOracleImpl()这部分,这就意味着你需要去改动已有的代码。如果你PersonService这段代码是在Jar文件里,那你岂不是还还没法改成Mysql数据库了呢,这是不是代表扩展性很差了呢。

设计原则中有特别重要的一条就是“开闭原则”:“对修改关闭,对扩展开放”,那我们这个设计的时候就违 背了这个重要的原则。

如果我将PersonService做一些调整(添加构造方法和set方法二选一即可):

public class PersonService {
    private PersonDao personDao;

    public PersonService(){}
    
	// 第一种方式,construct注入personDao
//	  public PersonService(PersonDao personDao){
//	   	  this.personDao = personDao;
//	  }
	
	// 第二种方式,set注入personDao
	public void setPersonDao(PersonDao personDao){
		this.personDao = personDao;
	}
    public Person getPerson() {
        return personDao.getPerson();
    }
}

我们在修改一下测试类(添加构造方法和set方法二选一即可,保持与上边一致):

public class IocTest {
    public static void main(String[] args) {
        // 第一种方式,construct注入personDao
//        PersonService personService = new PersonService();
//        PersonDao personDao = new PersonDaoOracleImpl(personService);
        // 第二种方式,set注入personDao
        PersonService personService = new PersonService();
        PersonDao personDao = new PersonDaoOracleImpl();
        personService.setPersonDao(personDao);
        System.out.println(personService.getPerson());
    }
}

结果:Person{id=0, name='Oracle', male=true}

这时我们更换为Mysql数据库应该怎么操作呢?是不是只需要将测试类中的PersonDaoOracleImpl实现改为PersonDaoMysqlImpl实现就可以了呢,这样就不用去动原有的代码,也不用担心它是Jar文件的内容,直接去新定义实现类来进行数据库切换,是不是代表了扩展性变好了呢。

D类:PersonDaoMysqlImpl

public class PersonDaoMysqlImpl implements PersonDao {
    @Override
    public Person getPerson() {
        return new Person(1, "Mysql", false);
    }
}

结果:Person{id=1, name='Mysql', male=false}

概念个人总结

以上就解释了容器提供的实现方式,“提供”也就是依赖注入,你依赖什么样的实现我就给你注入什么样的实现,那容器是从哪来的呢?以上的示例代码中并没有容器,提供的实现类也是我们手动new在测试类里的,但是Spring就不一样了,它实现了容器的机制,也就是IOC容器:

容器,顾名思义就是装东西的,并对外部提供东西的。那Spring这个IOC容器装什么?提供什么呢?通过上述的描述,我们已经知道了容器提供的实现方式,但是我们缺少容器提供的提供方啊,由此推断IOC容器是用来装各个实现类的,也称为装B(bean 可以理解为需要由Spring管理的类)的。

IOCIOC容器是两个概念,前者代表的是一种设计思想,后者代表的是一个容器,不要混淆。

最后我个人是这样总结的:IOC这种设计思想,是由IOC容器使用DI的方式提供来实现的

发布了14 篇原创文章 · 获赞 0 · 访问量 365

猜你喜欢

转载自blog.csdn.net/weixin_44601009/article/details/104310167
今日推荐