Spring——控制反转IOC(依赖注入DI)案例详解

1、new使用离散不易于管理

在理解控制反转之前我们先看一个简单的例子
我们想打印出学生所学习的课程信息,我们有一个课程接口(ICourse),有两门课程HtmlCourse和JavaCourse,如果是以前的话我们会这样写代码
接口ICourse:

public interface ICourse {
	//学习的课程
	void learn();
}

HtmlCourse.java

public class HtmlCourse implements ICourse {
	@Override
	public void learn() {
		// TODO Auto-generated method stub
		System.out.println("学习Html");
	}
}

JavaCourse.java

public class JavaCourse implements ICourse {
	@Override
	public void learn() {
		// TODO Auto-generated method stub
		System.out.println("学习Java");
	}
}

然后会有一个学生类Student:

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sty.factory.CourseFactory;
import com.sty.newinstance.HtmlCourse;
import com.sty.newinstance.ICourse;
import com.sty.newinstance.JavaCourse;

public class Student {
	private int stuNo;
	private String name;
	private String age;
	
	public int getStuNo() {
		return stuNo;
	}
	public void setStuNo(int stuNo) {
		this.stuNo = stuNo;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAge() {
		return age;
	}
	public void setAge(String age) {
		this.age = age;
	}
	
	
	//创建对象太麻烦,很离散,加入有很多们课程,就会new很多各对象
	
	//要学习javaClass
	public void learnJava() {
		ICourse course = new JavaCourse();
		course.learn();
	}
	
	//要学习htmlClass
	public void learnhtml() {
		ICourse course = new HtmlCourse();
		course.learn();
	}

	@Override
	public String toString() {
		return "Student [stuNo=" + stuNo + ", name=" + name + ", age=" + age + "]";
	}

}

最后我们在Test里面调用这两个方法打印学生学课信息

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sty.Student;

public class Test {
	
	
	//最原始的做法,去创建对象,并且里面的每一个方法都是用new的形式,很离散,修改的时候和麻烦,会找到很多的方法
	
	 public static void learnCourseNew() {
	  Student stu = new Student();
	  stu.learnhtml(); 
	  stu.learnJava(); 
	 }

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		learnCourseNew();
	}

}

最终上面会打印出学习java和学习Html,然而这种方法在上面的注释也提到了,那就是在面对很多课程的时候无疑是很复杂的,不断的new对象,也不方便管理


2、可以创建一个课程工厂(CourseFactory)来帮助我们管理这些new的对象

CourseFactory.java

import com.sty.newinstance.HtmlCourse;
import com.sty.newinstance.ICourse;
import com.sty.newinstance.JavaCourse;

//课程工厂
public class CourseFactory {
	public static ICourse getCourse(String name) {

		if(name.equals("java")) {
			return new JavaCourse();
		}else {
			return new HtmlCourse();
		}
	}
}

Test里面创建新的方法在main里面调用

//用一个工厂,将new都放到一个工厂中来实现,修改的时候就只需要找到对应的方法
	
	  public static void learnCourseWithFactory() { 
	  Student stu = new Student();
	  stu.learn("java");
	  
	  }
	 

Student添加新的方法


	  //学习任何课程 
	  public void learn(String name) { 
	  ICourse course = CourseFactory.getCourse(name); //course就是根据传入的名字返回具体的课程,然后调用自己课程的学习方法
	 course.learn();
	 
	  }
	 

这样就可以根据你传进来的课程值,打印出对应的学习课程而且,有改动的时候,只需要找到这个方法就行。第一中方式,就会找到多个方法进行修改,当方法多的时候,就很费劲。可是在我们的Test里面的learn方法中一句会去new那个新建的工厂,可不可以不用new呢?


3、Spring的IOC容器可以替代这个工厂CourseFactory

在配置好Spring环境后(其实就是在你的java项目添加几个jar包),
spring-aop-4.3.9.RELEASE.jar//开发AOP特性需要用到,
spring-beans-4.3.9.RELEASE.jar//写bean表达式要用到
spring-context-4.3.9.RELEASE.jar//处理spring上下文
spring-core-4.3.9.RELEASE.jar//核心包,Spring工程必须有这个包
spring-expression-4.3.9.RELEASE.jar//Spring表达式(EL)
commons-logging-1.1.1.jar//日志
新建一个Spring bean.xml文件(applicationContext.xml)(右键->other->输入bean(在确保你安装了spring-tools-suite)->选择Spring下的Spring bean Configuration File)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">



<!-- 该文件中的所有对象都在spring容器中 -->
<!-- id唯一标识符  class指定类型 -->
	<bean id="student" class="com.sty.Student">
	<!-- property属性 -->
		<property name="stuNo" value="1"></property>
		<property name="name" value="ls"></property>
		<property name="age" value="25"></property>
	</bean>
	
	<!-- 注入htmlCourse类 -->
	<bean id="htmlCourse" class="com.sty.newinstance.HtmlCourse" >
		
	</bean>

<!-- 注入javaCourse类 -->
	<bean id="javaCourse" class="com.sty.newinstance.JavaCourse" >
		
	</bean>
</beans>

将Student里面的learn方法修改一下(注意导包)

// 学习任何课程
	public void learn(String name) {
		/*
		 * 不需要工厂了 ICourse course = CourseFactory.getCourse(name);
		 * //course就是根据传入的名字返回具体的课程,然后调用自己课程的学习方法 course.learn();
		 */
		// 从容器里面拿
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		//getBean()方法依据之前注入的id值获取定义的类
		ICourse course = (ICourse) context.getBean(name);
		// 通过获取到的课程类型在进入各自的学习方法
		course.learn();
	}

因此Test里面的方法也改变一下

//SPringIOC
	public static void learnCourseWithIOC() {
		//不需要new对象,也是先通过获取上下文
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC获取学生对象
		Student stu = (Student)context.getBean("student");
		stu.learn("htmlCourse");//课程名
	}

使用第三种方法,我们就可以不使用new的方式获取或者创建对象,并且当你需要修改的时候,只需要修改Test类中learnCourseWithIOC方法传入的课程名


总结:

怎样理解控制反转(IOC):
比如第一种方法,我们不管怎样都要去new对象来实现我们的功能,我们需要设定一些我们想要的东西,比如属性值呀等等,总之必须由你自己来设计。现在就是说Spring有一个容器,你只需要告诉他,你想设置什么值,你以后要用的时候久来取,我先帮你管理着,这时候Spring就充当着你以前的角色,这就是控制反转。
什么又叫依赖注入(DI):
其实DI和IOC可以说是一个意思,只是IOC可能不好理解,我的理解就是,在一个类中你可能会用到其他类怎么办?第一思路就是用new关键字创建一个你需要的类,对吧,可是这样会产生一个叫耦合性的问题:意思就是说,请不要在我自己的类中再去创建其他的类,让我自己能够独立起来,不想与其他类产生关联。
所以解决办法就是使用Spring容器,n我们只需要告诉Spring,这个类会依赖于其他的东西,具体怎么构造,合适构造,由Spring来完成,然后Spring自己会在适当的时候给这个类注入你依赖的东西,这就是依赖注入的由来


以上是本人通过实际课程案例,得出的一些心得,如果由错误或者不够完善的地方,还希望各位大神多多指教,谢谢!!
发布了93 篇原创文章 · 获赞 26 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_38261445/article/details/90142455