zoukankan      html  css  js  c++  java
  • Java之控制反转和依赖注入

    1.简介

    依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念。

    2.案例

    1)一般情况下的类耦合

    Main.java

    public class Main {
         public static void main(String[] args) {
              /******** 一般写法,Main类与Chinese类和American类之间的强耦合 ***********/
              // Chinese和American,当类和方法修改时,此处的类和方法也需要修改
              Chinese chinese = new Chinese();
              chinese.sayHelloWorld("张三");
    
              American american = new American();
              american.sayHelloWorld("Jack");
         }
    }
    
    /******************** 一般方法 ***************************/
    
    interface Human {
         public void sayHelloWorld(String name);
    }
    
    
    class Chinese implements Human {
         public void sayHelloWorld(String name) {
              String helloWorld = "你好," + name;
              System.out.println(helloWorld);
         }
    }
    
    class American implements Human {
         public void sayHelloWorld(String name) {
              String helloWorld = "Hello," + name;
              System.out.println(helloWorld);
         }
    }

    通过上面代码可以看出:Main类与Chinese类和American类之间存在着强耦合 , Chinese和American类和方法修改时,此处的类和方法也需要修改。不容易扩展和维护。

    2)工厂方法来解耦合

    public class Main {
         public static void main(String[] args) {
              /******** 工厂方法, Main类与类Chinese和American不再耦合,仅仅和其接口Human耦合 ***********/
              // 修改时还需要修改在Main类中修改这些字符串
              // Chinese和American,当类和方法修改时,只有方法需要修改
              HumanFactory humanFactory = new HumanFactory();
              Human human1 = humanFactory.getHuman("chinese");
              human1.sayHelloWorld("张三");
    
              Human human2 = humanFactory.getHuman("american");
              human2.sayHelloWorld("Jack");
         }
    }
    
    
    /******************** 工厂方法 ***************************/
    interface Human {
         public void sayHelloWorld(String name);
    }
    
    class HumanFactory {
         public Human getHuman(String type) {
              if ("chinese".equals(type)) {
                   return new Chinese();
              } else {
                   return new American();
              }
         }
    }


    通过上面代码可以看出:Main类与类Chinese和American不再耦合,仅仅和其接口Human耦合,修改时还需要修改在Main类中修改这些字符串,当类和方法修改时,只有方法需要修改。这一定程度上降低了Main类和Chinese、American类的耦合

    3)依赖注入和控制反转

    public class Main {
         public static void main(String[] args) {
              /******************** IOC控制反转和依赖注入 ***************************/
              // 利用容器,通过xml文件直接注入属性值,在Main类中只添加需要的
              // Chinese和American,当类和方法修改时,代码完全不用修改,只需要修改xml文件即可,彻底实现了解耦
              BeanFactory beanFactory = new BeanFactory();
              beanFactory.init("/config.xml");
              UserBean userBean = (UserBean) beanFactory.getBean("userBean");
              System.out.println("userName=" + userBean.getUserName());
              System.out.println("password=" + userBean.getPassword());
         }
    }
    
    
    /******************** IOC控制反转和依赖注入 ***************************/
    // 下面是Spring的IOC实现:Bean工厂
    class BeanFactory {
         private Map<String, Object> beanMap = new HashMap<String, Object>();
    
         public void init(String fileName) {
              try {
                   // 读取指定的配置文件
                   SAXReader reader = new SAXReader();
                   // System.out.println(xmlpath);
                   String realPathString = new File("").getCanonicalPath();
                   Document document = reader.read(new File(realPathString + "/src/com/devin/") + fileName);
                   Element root = document.getRootElement();
                   Element foo;
                   // 遍历bean
                   for (Iterator i = root.elementIterator("bean"); i.hasNext();) {
                        foo = (Element) i.next();
                        // 获取bean的属性id和class
                        Attribute id = foo.attribute("id");
                        Attribute cls = foo.attribute("class");
                        // 利用Java反射机制,通过class的名称获取Class对象
                        Class bean = Class.forName(cls.getText());
                        // 获取对应class的信息
                        java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
                        // 获取其属性描述
                        java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
                        // 设置值的方法
                        Method mSet = null;
                        // 创建一个对象
                        Object obj = bean.newInstance();
                        // 遍历该bean的property属性
                        for (Iterator ite = foo.elementIterator("property"); ite.hasNext();) {
                             Element foo2 = (Element) ite.next();
                             // 获取该property的name属性
                             Attribute name = foo2.attribute("name");
                             String value = null;
                             // 获取该property的子元素value的值
                             for (Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) {
                                  Element node = (Element) ite1.next();
                                  value = node.getText();
                                  break;
                             }
                             for (int k = 0; k < pd.length; k++) {
                                  if (pd[k].getName().equalsIgnoreCase(name.getText())) {
                                       mSet = pd[k].getWriteMethod();
                                       mSet.invoke(obj, value);
                                  }
                             }
                        }
    
                        // 将对象放入beanMap中,其中key为id值,value为对象
                        beanMap.put(id.getText(), obj);
                   }
              } catch (Exception e) {
                   System.out.println(e.toString());
              }
         }
    
         // 通过bean的id获取bean的对象.
         public Object getBean(String beanName) {
              Object obj = beanMap.get(beanName);
              return obj;
         }
    }
    
    
    UserBean.java
    
    public class UserBean {
         private String userName;
         private String password;
    
         public String getPassword() {
              return password;
         }
    
         public String getUserName() {
              return userName;
         }
    
         public void setUserName(String userName) {
              this.userName = userName;
         }
    
         public void setPassword(String password) {
              this.password = password;
         }
    }
    
    config.xml
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
         <bean id="userBean" class="com.devin.UserBean">
              <property name="userName">
                   <value>张三</value>
              </property>
              <property name="password">
                   <value>Jack</value>
              </property>
         </bean>
    </beans>
    说明:模拟了Spring中IOC的实现,虽然只是完成了Spring中依赖注入的一小部分工作,但是很好的展现了Java反射机制在Spring中的应用,能使我们能更好的从原理上了解IOC的实现。
  • 相关阅读:
    WCF中的自定义类中包括自定义枚举类型时出错
    Asp.Net无刷新上传并裁剪头像
    C# 字符串模糊查找
    .NET中如何通过文本框中按回车键进行的提交数据
    关于Firefox、Safari 与IE区别实际应用的一点心得
    ASP.NET 网速慢时候按钮禁止重复提交
    ASP.NET前台代码绑定后台变量方法总结
    验证功能在IE中没问题,在火狐浏览器中无反应
    aspx 后台cs文件动态修改Lable 样式
    asp.net程序调试 连接池和 "Timeout expired"异常
  • 原文地址:https://www.cnblogs.com/devinzhang/p/3862942.html
Copyright © 2011-2022 走看看