美文网首页
Spring IoC简单实现

Spring IoC简单实现

作者: ryancao_b9b9 | 来源:发表于2018-05-02 12:48 被阅读0次

    1、概述

    Spring容器的原理就是基于解析XML文件、反射创建Bean、通过工厂模式管理Bean集合, 只需要调用getBean("beanID")方法即可获得这Bean。


    2、实现过程

    2.1 反射机制

    反射.png
    详情

    2.2 XML解析

    XML文件示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans>  
        <bean id="user" class="com.falcon.model.User" />  
        <bean id="userDAO" class="com.falcon.dao.impl.UserDAOImpl" />  
        <bean id="userService" class="com.falcon.service.UserService">  
            <property name="userDAO" bean="userDAO" />  
        </bean>  
    </beans> 
    

    ClassPathXmlApplicationContext:读取xml文件内容,并创建对象及对象关系(使用setter方式)

    package com.falcon.spring;
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import org.jdom.Document;
    import org.jdom.Element;
    import org.jdom.JDOMException;
    import org.jdom.input.SAXBuilder;
    public class ClassPathXmlApplicationContext implements BeanFactory
    {
        private Map<String, Object> beans = new HashMap<String, Object>();
        public ClassPathXmlApplicationContext() throws JDOMException, IOException,
                InstantiationException, IllegalAccessException,
                ClassNotFoundException, SecurityException, NoSuchMethodException,
                IllegalArgumentException, InvocationTargetException
        {
            SAXBuilder sb = new SAXBuilder();
            // 构造文档对象
            Document doc = sb.build(ClassPathXmlApplicationContext.class
                    .getClassLoader().getResourceAsStream("beans.xml"));
            // 获取根元素
            Element root = doc.getRootElement();
            // 取到根元素所有元素
            List list = root.getChildren();
            for (int i = 0; i < list.size(); i++)
            {
                Element element = (Element) list.get(i);
                // 取id子元素
                String beanid = element.getAttributeValue("id");
                // 取class子元素
                String clzss = element.getAttributeValue("class");
                // 实例化
                Object o = Class.forName(clzss).newInstance();
                // 将所有bean放入map中
                beans.put(beanid, o);
                // 获取property 进行依赖注入
                for (Element propertyElement : (List<Element>) element
                        .getChildren("property"))
                {
                    String name = propertyElement.getAttributeValue("name");
                    System.out.println(name);//userDAO
                    String bean = propertyElement.getAttributeValue("bean");
                    System.out.println(bean);//userDAO
                    // 从beans.xml中根据id取到类的对象
                    //Object beanObj = this.getBean(name);
                    // 从beans.xml中根据id取到类的对象
                    Object beanObj = this.getBean(bean);
                    System.out.println(beanObj);//com.yyb.dao.impl.UserDAOImpl@a09ee92
                    // 形成setXXX方法名
                    String methodName = "set" + name.substring(0, 1).toUpperCase()
                            + name.substring(1);
                    System.out.println(name.substring(0, 1).toUpperCase());//U
                    System.out.println(name.substring(1));//serDAO
                    System.out.println(methodName);//setUserDAO
                    
                    // 反射机制对方法进行调用,将对象在加载bean时就注入到环境上下文中
                    Method m = o.getClass().getMethod(methodName,
                            beanObj.getClass().getInterfaces()[0]);
                    System.out.println(o.getClass());//class com.yyb.service.UserService
                    System.out.println(beanObj.getClass().getInterfaces()[0]);//interface com.yyb.dao.UserDAO
                    System.out.println(m);//public void com.yyb.service.UserService.setUserDAO(com.yyb.dao.UserDAO)
                    // 执行注入,相当于执行了一个setXXX(args..)的方法
                    m.invoke(o, beanObj);
                }
            }
        }
        @Override
        public Object getBean(String name)
        {
            return beans.get(name);
        }
    }
    
    

    2.3 BeanFactory

    接口示例:

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

    Bean示例:

    public class User {
        private String userName;  
        private String password;  
        /** 
         * @return the userName 
         */  
        public String getUserName()  
        {  
            return userName;  
        }  
        /** 
         * @param userName 
         * the userName to set 
         */  
        public void setUserName(String userName)  
        {  
            this.userName = userName;  
        }  
        /** 
         * @return the password 
         */  
        public String getPassword()  
        {  
            return password;  
        }  
        /** 
         * @param password 
         *  the password to set 
         */  
        public void setPassword(String password)  
        {  
            this.password = password;  
        }  
        public String toString()  
        {  
            StringBuffer sb = new StringBuffer();  
            sb.append(this.userName);  
            sb.append(this.password);  
            return sb.toString();  
        }  
    }
    
    public interface UserDAO {
         void save(User u);  
         void delete(); 
    }
    
    public class UserDAOImpl implements UserDAO {
           @Override  
            public void save(User u) {  
                System.out.println("User:" + u.toString());  
            }  
            @Override  
            public void delete() {  
                System.out.println("delete User");  
            }  
    }
    
    public class UserService {
       private UserDAO userDAO;  
       public void addUser(User u)  
        {  
            this.userDAO.save(u);  
        }  
        /** 
         * @return the userDAO 
         */  
        public UserDAO getUserDAO()  
        {  
            return userDAO;  
        }  
        /** 
         * @param userDAO 
         *  the userDAO to set 
         */  
        public void setUserDAO(UserDAO userDAO)  
        {  
            this.userDAO = userDAO;  
        }  
    }
    

    2.4 自动依赖注入

    依赖注入核心部分

                          // 实例化
                Object o = Class.forName(clzss).newInstance();
                // 将所有bean放入map中
                beans.put(beanid, o);
                // 获取property 进行依赖注入
                for (Element propertyElement : (List<Element>) element
                        .getChildren("property"))
                {
                    String name = propertyElement.getAttributeValue("name");
                    System.out.println(name);//userDAO
                    String bean = propertyElement.getAttributeValue("bean");
                    System.out.println(bean);//userDAO
                    // 从beans.xml中根据id取到类的对象
                    //Object beanObj = this.getBean(name);
                    // 从beans.xml中根据id取到类的对象
                    Object beanObj = this.getBean(bean);
                    System.out.println(beanObj);//com.yyb.dao.impl.UserDAOImpl@a09ee92
                    // 形成setXXX方法名
                    String methodName = "set" + name.substring(0, 1).toUpperCase()
                            + name.substring(1);
                    System.out.println(name.substring(0, 1).toUpperCase());//U
                    System.out.println(name.substring(1));//serDAO
                    System.out.println(methodName);//setUserDAO
                    
                    // 反射机制对方法进行调用,将对象在加载bean时就注入到环境上下文中
                    Method m = o.getClass().getMethod(methodName,
                            beanObj.getClass().getInterfaces()[0]);
                    System.out.println(o.getClass());//class com.yyb.service.UserService
                    System.out.println(beanObj.getClass().getInterfaces()[0]);//interface com.yyb.dao.UserDAO
                    System.out.println(m);//public void com.yyb.service.UserService.setUserDAO(com.yyb.dao.UserDAO)
                    // 执行注入,相当于执行了一个setXXX(args..)的方法
                    m.invoke(o, beanObj);
                }
    

    实现效果:
    Service service=(Service)beans.get("userService");
    Dao dao = (Dao)beans.get("userDAO");
    //依赖注入,Service实现依赖dao的实现
    service.setDao(dao);


    3、测试

    public class client {
    
        public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException, JDOMException, IOException {
        BeanFactory factory = new ClassPathXmlApplicationContext(); 
        //通过工厂直接获取
            UserService userService = (UserService) factory.getBean("userService"); 
            //其实User也可以从工厂中获得
            User u=(User)factory.getBean("user");
            //User u = new User();  
            u.setUserName("yyb");  
            u.setPassword("1234");  
            userService.addUser(u);//打印结果yyb1234
        }
    
    }
    

    相关文章

      网友评论

          本文标题:Spring IoC简单实现

          本文链接:https://www.haomeiwen.com/subject/fjaalftx.html