我的学习之路-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,结构如下
在这里插入图片描述

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.结果

在这里插入图片描述

结语

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

java.lang.NoClassDefFoundError: org/jaxen/JaxenException at org.dom4j.DocumentFactory.createXPath(DocumentFactory.java:230) at org.dom4j.tree.AbstractNode.createXPath(AbstractNode.java:207) at org.dom4j.tree.AbstractNode.selectSingleNode(AbstractNode.java:183) at demo.TestXML.getTaskByName(TestXML.java:19) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunne
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值