• 自己实现简单Spring Ioc


    IoC则是一种 软件设计模式,简单来说Spring通过工厂+反射来实现IoC。

    原理简单说明:
    其实就是通过解析xml文件,通过反射创建出我们所需要的bean,再将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这bean。
    通俗来讲就如同婚姻介绍所,只需要告诉它找个什么样的女朋友,然后婚介就会按照我们的要求,提供一个mm,如果婚介给我们的人选不符合要求,我们就会抛出异常。

    简单实现:


    1.需要引用maven依赖:

     <dependency>
                <groupId>org.jdom</groupId>
                <artifactId>jdom</artifactId>
                <version>1.1.3</version>
            </dependency>
    

    2.beans.xml

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

    3.BeanFactory

    package com.example.ioc;
    
    public interface BeanFactory {
        Object getBean(String name);
    }
    
    

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

    package com.example.ioc;
    
    import org.jdom.Document;
    import org.jdom.Element;
    import org.jdom.input.SAXBuilder;
    
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    
    public class ClassPathXmlApplicationContext implements BeanFactory {
        private Map<String, Object> beans = new HashMap<String, Object>();
    
        public ClassPathXmlApplicationContext() throws Exception {
            SAXBuilder sb = new SAXBuilder();
            // 构造文档对象
            Document doc = sb.build(ClassPathXmlApplicationContext.class
                    .getClassLoader().getResourceAsStream("beans.xml"));
            // 获取根元素
            Element root = doc.getRootElement();
            // 取到根元素所有元素
            List list = root.getChildren();
    
            setBeans(list);
        }
    
        //设置Bean
        private void setBeans(List list) throws Exception {
            for (int i = 0; i < list.size(); i++) {
                Element element = (Element) list.get(i);
                String id = element.getAttributeValue("id");
                //取得class子元素
                String clzss = element.getAttributeValue("class");
                //通过反射进行实例化
                Object o = Class.forName(clzss).newInstance();
                beans.put(id, o);
    
                setProperty(element, o);
            }
        }
    
        //获取property进行依赖注入
        private void setProperty(Element element, Object o) throws Exception {
            for (Element property : (List<Element>) element.getChildren("property")) {
                String name = property.getAttributeValue("name");
                String bean = property.getAttributeValue("bean");
                //从beans.xml中根据id取到类的对象
                Object beanObj = this.getBean(bean);
                System.out.println(beanObj);//com.example.dao.impl.UserDAOImpl@2f4d3709
                //组成setXXX方法名
                String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
                // 反射机制对方法进行调用,将对象在加载bean时就注入到环境上下文中
                Method m = o.getClass().getMethod(methodName, beanObj.getClass().getInterfaces()[0]);
                m.invoke(o, beanObj);
            }
        }
    
    
        @Override
        public Object getBean(String name) {
            return beans.get(name);
        }
    }
    
    
    
    

    以上为核心代码,当然在实际情况中,这一块要复杂的多, 例如:可以一个bean引用另一个bean,还可以有多个配置文件、通过多种方式载入配置文件等等,不过原理还是采用Java的反射机制。

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

    5.User:实体类

    package com.example.domain;
    
    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();
        }
    }
    
    

    6.UserDAO

    package com.example.dao;
    
    import com.example.domain.User;
    
    public interface UserDAO {
        void save(User u);
    
        void delete();
    }
    
    

    7.UserDAOImpl

    package com.example.dao.impl;
    
    import com.example.dao.UserDAO;
    import com.example.domain.User;
    
    
    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");
    
        }
    }
    
    

    8.UserService

    package com.example.service;
    
    import com.example.dao.UserDAO;
    import com.example.domain.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;
        }
    }
    
    

    9.测试:

    package com.example.ioc;
    
    import com.example.domain.User;
    import com.example.service.UserService;
    
    
    public class RunIoc {
        public static void main(String[] args) throws Exception {
            BeanFactory factory = new ClassPathXmlApplicationContext();
            //通过工厂直接获取
            UserService userService = (UserService) factory.getBean("userService");
            //其实User也可以从工厂中获得
            User u = (User) factory.getBean("user");
            //User u = new User();
            u.setUserName("tom");
            u.setPassword("123456");
            userService.addUser(u);//打印结果tom123456
        }
    }
    
    

    小结

    上文仅仅是简单地模拟了spring的IOC的实现,虽然只是完成了spring中依赖注入的一小部分,但还是很好地展现了Java反射机制在spring中的应用

  • 相关阅读:
    FLINK 设计文档
    prometheus-dashboard-to-grafana
    apache-flink-training-metrics-monitoring
    多个inputstream的情况下,watermark的值怎么赋值? kakfa中多个partition提取 watermark
    how-apache-flink-enables-new-streaming-applications-part-1
    Advanced DataStream API Low-latency Event Time Join
    checkpoint and savepoint in FlinK
    Flink connectedstreams
    FLINK 案例分析
    Apache 流框架 Flink,Spark Streaming,Storm对比分析(一)
  • 原文地址:https://www.cnblogs.com/lspz/p/6244948.html
Copyright © 2020-2023  润新知