Spring笔记(第一弹:简单模拟Spring IOC)

Spring博大精深,功能非常多。我们这里简单的模拟一下spring的IOC。

先把model,dao,service写出来,写一个最简单的为例。
在model包下定义一个User:

package com.hello.model;

public class User {

    private String userId;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    private String userName;
}

在dao包下定义一个UserDAO:

package com.hello.dao;

import com.hello.model.User;

public interface UserDAO {

    public void add(User user);

}

在dao.impl包下定义一个UserDAOImpl:

package com.hello.dao.impl;

import com.hello.dao.UserDAO;
import com.hello.model.User;

public class UserDAOImpl implements UserDAO {

    @Override
    public void add(User user) {
        System.out.println("A user added!");
    }

}

在service包下定义一个UserService:

package com.hello.service;

import com.hello.model.User;

public interface UserService {

    public void add(User user);
}

在service.impl包下定义一个UserServiceImpl:

package com.hello.service.impl;

import com.hello.dao.UserDAO;
import com.hello.model.User;
import com.hello.service.UserService;

public class UserServiceImpl implements UserService {

    private UserDAO userDAO;

    public UserDAO getUserDAO() {
        return userDAO;
    }

    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    @Override
    public void add(User user) {
        userDAO.add(user);
    }

}

注意这个UserServiceImpl里的userDAO属性要提供好get,set方法,因为我们后面要通过反射机制,把dao给set进来。

下面就是重头戏了,我们要模拟spring,自然要写一个ApplicationContext.xml:

<beans>
    <bean id="userDAOImpl" class="com.hello.dao.impl.UserDAOImpl" />

    <bean id="userServiceImpl" class="com.hello.service.impl.UserServiceImpl">
        <property name="userDAO" ref="userDAOImpl"></property>
    </bean>
</beans>

再模拟一个BeanFactory:

package com.hello.spring;

public interface BeanFactory {
    public Object getBean(String name);
}

再来一个ClassPathXmlApplicationContext,实现BeanFactory接口:

package com.hello.spring;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

public class ClassPathXmlApplicationContext implements BeanFactory {

    // 从配置文件里解析出来的所有的bean都会放在这个容器里
    private Map<String, Object> beans = new HashMap<String, Object>();

    public ClassPathXmlApplicationContext() throws Exception {
        SAXBuilder sb = new SAXBuilder();
        // 读取配置文件
        Document document = sb.build(this.getClass().getClassLoader().getResourceAsStream("ApplicationContext.xml"));
        // 获取跟节点,即beans节点
        Element rootElement = document.getRootElement();
        // 获取所有的bean节点
        List<Element> elementList = rootElement.getChildren("bean");
        // 遍历每一个bean节点,把所有的bean都放到beans容器中,并对每一个bean进行自动装配
        for (int i = 0; i < elementList.size(); i++) {
            // 读取bean节点的id和class属性
            Element element = elementList.get(i);
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");
            // 通过反射获取这个class对应的实例
            Object o = Class.forName(clazz).newInstance();
            // 放入到beans容器中
            beans.put(id, o);

            // 遍历这个bean中所有的property节点
            for (Element propertyElement : element.getChildren("property")) {
                // 读取property节点的name属性,这个name就是要注射的bean的名字
                String name = propertyElement.getAttributeValue("name");
                // 读取property节点的ref属性,这个ref就是在beans容器中的bean的名字
                String ref = propertyElement.getAttributeValue("ref");
                // 从beans容器中获取到这个ref所对应的bean
                Object refBeanObject = beans.get(ref);
                // 根据name,构造出set方法的方法名
                String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
                // 根据方法名和参数获取到set方法
                Method m = o.getClass().getMethod(methodName, refBeanObject.getClass().getInterfaces()[0]);
                // 调用set方法,进行注射。这样就实现了自动装配
                m.invoke(o, refBeanObject);
            }
        }
    }

    @Override
    public Object getBean(String name) {
        return beans.get(name);
    }

}

以上已经模拟完成,我们测试一下:

package com.hello.spring;

import com.hello.model.User;
import com.hello.service.UserService;

public class test {

    public static void main(String[] args) throws Exception {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext();
        UserService userService = (UserService) beanFactory.getBean("userServiceImpl");
        userService.add(new User());
    }

}

运行一下,可以看到控制台输出:

A user added!

到此,我们已经成功的模拟了一个最简单的spring。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值