天天看点

我的学习之路-Spring Ioc

加深spring框架理解,实现简单的Ioc容器

最近学习到了SSM框架,记录一下spring的Ioc容器学习。

什么是Ioc?

Ioc 英文就是 Inversion Of Control,意思是控制反转。

IoC 是指在程序开发中,实例的创建不再由调用者管理,而是由 Spring 容器创建。Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的 IoC 思想。

简单一点说,就是以前我们创建对象的时候,要自己敲,new 一个新对象,现在把创建对象的任务交给spring容器处理,由spring容器创建对象,我们直接使用就好。

思想简单理解

我们将需要创建的对象和依赖关系通过bean标签的形式写入配置文件(applicationContext.xml),框架读取配置文件,创建对象并处理依赖关系。

写一个简单的Ioc容器

创建实体对象类,将类信息写入applicationContext.xml文件,初始化容器,读取配置文件,获得类信息,数据信息,利用反射机制获得类对象,创建类,将数据注入类。

实现

1.创建项目

项目名 easyIoc,结构如下

我的学习之路-Spring Ioc

2.实体类:Apple

package com.Ioc.entity;

public class Apple {
    private String name;
    private String color;
    private String taste;

    @Override
    public String toString() {
        return "Apple{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", taste='" + taste + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getTaste() {
        return taste;
    }

    public void setTaste(String taste) {
        this.taste = taste;
    }
}

           

3.配置文件:applicationContext.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <bean id="redApple" class="com.Ioc.entity.Apple">
        <property name="name" value="红苹果"/>
        <property name="color" value="红色"/>
        <property name="taste" value="甜"/>
    </bean>
</beans>
           

4.接口类:applicationContext

package com.Ioc.context;

public interface ApplicationContext {
    public Object getBean(String beanId);
}
           

5.实现类:ClassPathXmlApplicationContext

package com.Ioc.context;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ClassPathXmlApplicationContext implements ApplicationContext {
    private Map IocContainer = new HashMap();

    public ClassPathXmlApplicationContext() {
        try {
//            读取xml配置文件
//            getResource用于从classpath获取指定文件资源 getPath获取路径
            String filePath = this.getClass().getResource("/applicationContext.xml").getPath();
//            URL解码,防止出现中文路径丢失问题
            filePath = new URLDecoder().decode(filePath, "UTF-8");
//            加载解析xml文件,获得Document对象
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File(filePath));
//            获取根节点集合
            List<Node> beans = document.getRootElement().selectNodes("bean");
            for (Node node : beans) {
//                强制转换成Element对象
                Element element = (Element) node;
//                提取属性
                String id = element.attributeValue("id");
                String className = element.attributeValue("class");
//                利用java反射获取类对象
                Class c = Class.forName(className);
//                接收类对象
                Object obj = c.newInstance();
//                获得属性节点
                List<Node> propertys = element.selectNodes("property");
                for (Node property : propertys) {
                    Element ele = (Element) property;
//                    获得属性名和属性值
                    String name = ele.attributeValue("name");
                    String value = ele.attributeValue("value");
//                    动态注入
//                    定义方法名,set后第一个字符大写
                    String setMethodName = "set" + name.substring(0,1).toUpperCase()+name.substring(1);
                    System.out.println("准备执行" + setMethodName + "方法注入数据");
//                    利用反射,通过方法名调用方法
//                    getMethod(),第一个参数:方法名,第二个参数:方法的参数的类型
                    Method setMethod = c.getMethod(setMethodName, String.class);
//                    调用方法
                    setMethod.invoke(obj, value);//通过setter方法注入数据
                }
//                放入容器
                IocContainer.put(id, obj);
            }
            System.out.println(IocContainer);
            System.out.println("初始化完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public Object getBean(String beanId) {
        return IocContainer.get(beanId);
    }
}
           

6.导入依赖:dom4j和jaxen (pom.xml)

<dependencies>
        <!--dom4j: java的xml解析组件,底层依赖jaxen-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <!--jaxen:Xpath表达式解释器-->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.2.0</version>
        </dependency>
    </dependencies>
           

7.程序入口:Application

package com.Ioc;

import com.Ioc.context.ApplicationContext;
import com.Ioc.context.ClassPathXmlApplicationContext;
import com.Ioc.entity.Apple;

public class Application {
    public static void main(String[] args) {
//        初始化容器
        ApplicationContext context = new ClassPathXmlApplicationContext();
        System.out.println((Apple)context.getBean("redApple"));
    }
}
           

8.结果

我的学习之路-Spring Ioc

结语

有问题希望大家指出。学无止境,欢迎交流。