版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
目录
一、环境
通过编译一个IOC容器,加深对IOC的理解。
二、具体实现
1.约定
所有Bean的生命周期交由loC容器管理
所有被依赖的Bean通过构造方法执行注入
被依赖的Bean需要优先创建
2.具体实现场景
张三和李四等有车一族,需要开车回家。
3.车类
(1)接口
package com.spring.ioc.self.car;
/**
* Created by Administrator on 2019/10/22.
*/
public interface Car {
public void start();
public void turnLeft();
public void turnRight();
public void stop();
}
(2)Audi
package com.spring.ioc.self.car;
/**
* Created by Administrator on 2019/10/22.
*/
public class Audi implements Car{
public void start() {
System.out.println("Audi start");
}
public void turnLeft() {
System.out.println("Audi turnLeft");
}
public void turnRight() {
System.out.println("Audi turnRight");
}
public void stop() {
System.out.println("Audi stop");
}
}
(3)Buick
package com.spring.ioc.self.car;
/**
* Created by Administrator on 2019/10/22.
*/
public class Buick implements Car {
public void start() {
System.out.println("Buick start");
}
public void turnLeft() {
System.out.println("Buick turnLeft");
}
public void turnRight() {
System.out.println("Buick turnRight");
}
public void stop() {
System.out.println("Buick stop");
}
}
4.人类
(1)人类接口
package com.spring.ioc.self.human;
/**
* Created by Administrator on 2019/10/22.
* 人类接口
*/
public interface Human {
/**
* 回家方法
*/
public void goHome();
}
(2)有车一族抽象类
package com.spring.ioc.self.human;
import com.spring.ioc.self.car.Car;
/**
* Created by Administrator on 2019/10/22.
* 有车一族:抽象类,因为方法无法具体形容,每个有车的人都有不同的回家方法
*/
public abstract class HumanWithCar implements Human {
/**
* 所有被依赖的Bean通过下面构造方法注入
*/
protected Car car;
/**
* 依据构造方法注入
* @param car
*/
public HumanWithCar(Car car) {
this.car = car;
}
@Override
public void goHome() {
}
}
(3)李四
package com.spring.ioc.self.human;
import com.spring.ioc.self.car.Car;
/**
* Created by Administrator on 2019/10/22.
* 李四
*/
public class LiSi extends HumanWithCar{
public LiSi(Car car) {
super(car);
}
@Override
public void goHome() {
// super.goHome();
car.start();
car.stop();
}
}
(4)张三
package com.spring.ioc.self.human;
import com.spring.ioc.self.car.Car;
/**
* Created by Administrator on 2019/10/22.
* 张三
*/
public class ZhangSan extends HumanWithCar{
public ZhangSan(Car car) {
super(car);
}
@Override
public void goHome() {
// super.goHome();
car.start();
car.turnLeft();
car.turnRight();
car.stop();
}
}
5.Ioc容器
package com.spring.ioc.self;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by Administrator on 2019/10/22.
* IOC容器
* 功能:
* 1.实例化bean
* 2.保存bean
* 3.提供bean
*
* 4.每一个bean要产生一个唯一一个id与之对应
*/
public class IoCContainer {
private Map<String,Object> beans= new ConcurrentHashMap<String,Object>();
/**
* get方法:根据beanId获得一个Bean
* @param beanId beanId
* @return 返回bean
*/
public Object getBean(String beanId) {
return beans.get(beanId);
}
/**
* set方法:委托ioc容器创建一个bean
* @param clazz 要创建的bean的class
* @param beanId bean的id
* @param paramBeanIds 要创建的bean的构造方法所需要的参数beanId们
*
*/
public void setBeans(Class<?> clazz,String beanId, String... paramBeanIds) {
//1.组装构造方法所需的参数值
Object[] paramValues=new Object[paramBeanIds.length];
for (int i=0;i<paramBeanIds.length;i++){
//因为被依赖的bean都会提前创建
paramValues[i]=beans.get(paramBeanIds[i]);
}
//2.调用构造方法实例化bean
Object bean=null;
// 获得所有类的构造函数
for (Constructor<?> constructor : clazz.getConstructors()) {
try {
bean=constructor.newInstance(paramValues);
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
//所有异常都不做处理,因为至少有一个构造方法是可以满足这些参数构造的
}
//如果还是没有实例化,即为null,则报错!
if(bean==null){
throw new RuntimeException("找不到合适的构造方法去实例化bean");
}
//3.将实例化的bean放入beans
beans.put(beanId,bean);
}
}
6.测试类
package com.imooc.ioc.self;
import com.spring.ioc.self.IoCContainer;
import com.spring.ioc.self.car.Audi;
import com.spring.ioc.self.car.Buick;
import com.spring.ioc.self.human.Human;
import com.spring.ioc.self.human.LiSi;
import com.spring.ioc.self.human.ZhangSan;
import org.junit.Before;
import org.junit.Test;
/**
* Created by Administrator on 2019/10/22.
* 测试ioc容器
*/
public class iocSelfTest {
/**
* 创建容器实例
*/
private IoCContainer ioccontainer=new IoCContainer();
@Before
public void before(){
ioccontainer.setBeans(Audi.class,"audi");
ioccontainer.setBeans(Buick.class,"buick");
ioccontainer.setBeans(ZhangSan.class,"zhangsan","audi");
ioccontainer.setBeans(LiSi.class,"lisi","buick");
}
@Test
public void test(){
//张三
Human zhangsan=(Human) ioccontainer.getBean("zhangsan");
zhangsan.goHome();
//李四
Human lisi=(Human) ioccontainer.getBean("lisi");
lisi.goHome();
}
}
运行结果:
Audi start
Audi turnLeft
Audi turnRight
Audi stop
Buick start
Buick stop
7.总结
(1)所有的依赖关系被集中统一的管理起来,清晰明了
(2)每个类只需要关注于自己的业务逻辑
(3)修改依赖关系将是一件很容易的事情
三、通过spring实现IOC
1.实现功能
创建一个简单的spring管理ioc实例,对比之前的自定义ioc,加深对Ioc控制反转的理解。
2.创建步骤
(1)添加依赖
<!--spring核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
(2)在resources下添加spring.xml,从而spring可以管理javabean
添加spring.xml基本标识
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-autowire="byName"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!--<context:component-scan base-package="com.znsd.vote" />-->
<bean id="bean" class="com.spring.ioc.Bean" />
<!--<bean id="test" class="com.springlearn.Test.RegisterPostAction" scope="prototype"/>
-->
<!-- dao -->
<!-- <bean id="userDao" class="com.springlearn.Test.UserDaoImpl" />
-->
</beans>
(3)创建类
package com.spring.ioc;
/**
* Created by Administrator on 2019/10/23.
*/
public class Bean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(4)在spring.xml中添加需要管理的bean
<bean id="bean" class="com.spring.ioc.Bean" />
(5)单元测试
package com.spring.ioc;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by Administrator on 2019/10/23.
*/
public class simpleSpringTest {
@Test
public void test(){
//从classpath路径下找名为"spring.xml"的配置文件
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
Bean bean=context.getBean("bean",Bean.class);
System.out.println("bean="+bean);
}
}
结果:
bean=com.spring.ioc.Bean@6c49835d
3.总结步骤
(1)添加spring相关依赖
(2)创建spring.xml配置文件,添加需要被spring管理的bean
(3)代码实现:获取spring上下文
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
(4)代码实现:获取Bean
Bean bean=context.getBean("bean",Bean.class);
四、参考
1.慕课网课程:https://www.imooc.com/video/19047
2.Github放有源码