为了账号安全,请及时绑定邮箱和手机立即绑定

【Spring核心概念之IOC】

标签:
Java

就目前来说我想很少有公司不使用spring框架了,那spring的优势我就不在这里说了,要是有朋友关心的话可以去看看百度百科怎么说的。

今天主要呢就是想自己实现一个类似spring的IOC框架。

  1. 首先我们确认下spring的概念,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架(来自百度百科)。其实还应该是一个容器框架。那么这就简单了,容器还能实现一对一,在我们学的Collection集合框架里面,只有map这个类库是最合适的。
  2. 其次,就是你得会反射。反射重要性我就不说了,现在的开源框架里面什么注解、代理都是利用了反射的技术,这个不得不会
  3. 再者就是解析xml,这个慕课网也有的,解析的方式有很多,只要会一种就可以了,因为其他的自己可以看官方手册。
    下面就正式上代码了
    首先我们定义一个接口 BeanFactory 、里面只有一个方法就是getBean,顺便说一句spring的名字也是这个BeanFactory的侧重点是Factory,就是一个能生产各种各样的Bean的这么一个类,当然spring还有一个类是XmlFactory不过这个已经过时了,不推荐使用
package com.hanson.custom.ioc;

/**
 * 
 * @ClassName: BeanFactory   
 * @Description:根据ID获取对象
 * @author: hanson
 * @date: 2016年8月9日 上午9:44:36   
 *
 */
public interface BeanFactory {
    public Object getBean(String id);
}

当然了首先得定义一个xml,这个xml我们就叫做beans.xml里面内容如下

<beans>
    <!--id可以看作一个别名,class:用的是dao实现类不是dao接口-->
    <bean id="userDao" class="com.hanson.dao.impl.UserDaoImpl"></bean>
    <bean id="userService" class="com.hanson.service.impl.UserServiceImpl">
        <!--有一个userDao属性,
            property:顾名思义就是属性的意思,
            name:UserServiceImpl类中的一个属性名称要和name对应
            ref:由于这个属性是一个引用对象,随意用ref,非引用对象可以使用value
            -->
        <property name="userDao" ref="userDao"></property>  
    </bean> 
</beans>

然后定义一个ioc容器我打算名字都跟spring的一样,就叫ClassPathXmlApplicationContext并实现BeanFactory,另外我解析xml使用的是jdom,你也可以使用dom4j(盗梦空间)。
整体代码如下:

package com.hanson.custom.ioc;

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;

/**
 * 
 * @ClassName: ClassPathXmlApplicationContext
 * @Description:自定义一个Ioc容器
 * @author: hanson
 * @date: 2016年8月9日 上午10:10:19
 * 
 */
public class ClassPathXmlApplicationContext implements BeanFactory {
    private static final Map<String, Object> beanMap = new HashMap<String, Object>();

    public ClassPathXmlApplicationContext(String xmlPath) throws Exception {
        SAXBuilder sb = new SAXBuilder();
        // 构造文档对象
        Document doc = sb.build(this.getClass().getClassLoader()
                .getResourceAsStream(xmlPath));
        // 获取根元素Beans
        Element root = doc.getRootElement();
        // 获取子元素bean
        List<Element> list = root.getChildren("bean");
        // 遍历
        for (int i = 0; i < list.size(); i++) {
            Element element = list.get(i);// 第i个
            // 获取id的值
            String id = element.getAttributeValue("id");
            // 获取class的值
            String className = element.getAttributeValue("class");
            // 利用反射得到一个真实对象
            Object obj = Class.forName(className).newInstance();
            // 存入Map
            beanMap.put(id, obj);
            // 遍历property属性
            List<Element> propertyElements = element.getChildren("property");
            for (Element propertyElement : propertyElements) {
                // 得到userDao
                String propertyName = propertyElement.getAttributeValue("name");
                String beanName = propertyElement.getAttributeValue("ref");
                Object refObject = beanMap.get(beanName);
                // 构造一个属性的setter方法
                String methodName = "set"
                        + propertyName.substring(0, 1).toUpperCase()
                        + propertyName.substring(1);
                // 获取指定的方法
                Method method = obj.getClass().getMethod(methodName,
                        refObject.getClass().getInterfaces()[0]);
                method.invoke(obj, refObject);
            }
        }
    }

    @Override
    public Object getBean(String id) {
        return beanMap.get(id);
    }

}

测试代码:

import com.hanson.custom.ioc.ClassPathXmlApplicationContext;
import com.hanson.service.UserService;

public class Demo {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
                "beans.xml");
        UserService userService = (UserService) ctx.getBean("userService");
        userService.say();
    }
}

最后附上其他几个用到的类:
UserDao接口

package com.hanson.dao;

public interface UserDao {
    public void say();
}

UserDaoImpl实现类

package com.hanson.dao.impl;
import com.hanson.dao.UserDao;
public class UserDaoImpl implements UserDao {
    @Override
    public void say() {
        System.out.println("Hello Ioc");
    }
}

UserService接口

package com.hanson.service;

public interface UserService {
    public void say();
}

UserServiceImpl实现类

package com.hanson.service.impl;

import com.hanson.dao.UserDao;
import com.hanson.service.UserService;

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void say() {
        userDao.say();
    }
}

本文代码使用到的jar只用jdom。本文目的是为了便于学习spring的人了解一下IOC的实现机制。

点击查看更多内容
17人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
334
获赞与收藏
3452

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消