zoukankan      html  css  js  c++  java
  • 1.IOC原理模拟

    Spring两大核心功能,IOC(Inverse  of  Control)  和 AOP(Aspect-Oriented-Programming)

    IOC原理模拟:

      有这样一个beans.xml:

    1 <beans>
    2     <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" />
    3     <bean id="userService" class="com.bjsxt.service.UserService" >
    4         <property name="userDAO" ref="u"/>
    5     </bean>
    6     
    7 </beans>

    现在我们想读取这个配置文件,实例化里面所有的bean,将其放到我们的容器中

    1. 首先我们的容器是一个 Map,里面存放我们bean的实力对象

    private Map<String,Object> beans = new HashMap<String,Object>();

    2.开始解析这个配置文件

      a)读取这个配置文件,先获取这个配置文件的根节点,再获取根节点下所有标签名为 <bean> 的节点

    1 Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); // 构造文档对象
    2         Element root = doc.getRootElement();            //获取根元素
    3         List list = root.getChildren("bean");           //获得根节点下所有标签名为 bean 的节点

      b)遍历所有的<bean>节点,拿到里面的 id 属性和 class属性

    for(int i=0;i<list.size();i++) {
                Element element=(Element)list.get(i);
                String id=element.getAttributeValue("id");
                String clazz=element.getAttributeValue("class");

      

      c)根据每个bean中的class属性的值,创建这个类的一个实例,将这个实例对象作为 value,bean中的id属性作为 key ,put进我们的容器中

    Object o = Class.forName(clazz).newInstance();
    beans.put(id, o);      //key 为 id 属性,value为 class 属性的实例

      d)遍历所有的<bean>节点,判断 <bean> 节点后面是否还有 <property>节点

       如果有的话,说明 这个bean中还需要注入其他实例对象 作为 属性 注入给它,所以我们需要继续去读这个 <property>,拿到 <property> 的 name 属性 和 ref属性

    for(Element propertyElement : (List<Element>)element.getChildren("property")) {            //如果某个bean中,存在property,即 存在 set***方法,则将xml文件指定的class注入进行
                   String name = propertyElement.getAttributeValue("name");   //userDAO
                   String ref= propertyElement.getAttributeValue("ref");   //u

      e)ref关联的是 某个 bean的id,所以通过ref属性,就可以 get 出 对应的实例对象,用于注入

     Object beanObject = beans.get(ref);                 //UserDAOImpl instance

      

      f)既然某个bean 希望 有 另外一个bean 可以注入进来,那么肯定要有对应 set方法,这个时候就需要用到 name 属性

      通过name属性,得到 注入的位置,如这里 name属性的值是 userDAO,说明该bean 需要一个UserDAO 类型的属性

      通过字符串拼接得到 setUserDAO方法,

    String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);        //拼接成setUserDAO

      

      g)反射调用该方法,完成 bean 的注入

    Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);   //反射调用 setUserDAO 方法,将userDao 注入 到 userService中
    m.invoke(o, beanObject);

      h)外界调用

      当程序一启动,就启动我们的容器,读取配置文件,完成bean 初始化和 注入,放到我们容器中

      UserService service = (UserService) applicationContext.getBean("userService");

      getBean方法,实际上就是 调用我们 容器(Map)的 get方法,通过 bean节点的id属性,拿到对象bean的实例

  • 相关阅读:
    《Think in Java》(十四)类型信息
    《Think in Java》(十三)字符串
    《Think in Java》(十二)通过异常处理错误
    《Think in Java》(十七)容器深入研究
    《Think in Java》(十一)持有对象
    集合框架概览
    Gulp 自动化构建过程
    自动化打包 CSS
    更新 Node 稳定版本命令
    mac 命令行打开vscode
  • 原文地址:https://www.cnblogs.com/xuzekun/p/7391163.html
Copyright © 2011-2022 走看看