Spring(1):实现自定义的IOC控制反转和通过spring实现IOC

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/u010886217/article/details/102692889

目录

一、环境

二、具体实现

三、通过spring实现IOC

四、参考


一、环境

通过编译一个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放有源码

猜你喜欢

转载自blog.csdn.net/u010886217/article/details/102692889
今日推荐