Java之控制反转和依赖注入

简介: Java之控制反转和依赖注入 1.简介依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念。 2.案例1)一般情况下的类耦合Main.

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 {
               // 读取指定的配置文件 ,采用dom4j的方法解析xml
               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>
复制代码
目录
相关文章
|
7月前
|
设计模式 Java 测试技术
Java 中的依赖注入和控制反转(IoC)
【4月更文挑战第19天】Java编程中的依赖注入和控制反转(IoC)是提升代码可维护性、可测试性和灵活性的关键设计模式。依赖注入通过外部注入对象依赖,减少硬编码,而IoC则是将控制权交给外部框架或容器。两者带来松耦合、可测试性、代码重用和灵活性。实现方式包括Spring框架和手动注入。使用框架能提供额外功能并简化管理,但要注意明确依赖关系、避免过度依赖和选择合适注入方式。依赖注入和IoC是构建健壮系统的有效工具。
53 2
|
XML 设计模式 存储
Java Spring IOC容器与依赖注入DI实现原理
本文主要讲解Spring IOC机制和实现过程,依赖注入DI和面向切面编程AOP是Spring框架的核心概念,几乎后续使用到Spring Boot框架的地方都有这两个概念的影子。也是Java面试的考察点,我们会结合实际的例子演示说明 。
909 1
|
2月前
|
Java 关系型数据库 测试技术
JAVA的依赖注入--搞不定的方式
JAVA的依赖注入--搞不定的方式
31 0
|
4月前
|
Java 测试技术 Spring
Java 新手入门:依赖注入的 N 种姿势,总有一款适合你!
Java 新手入门:依赖注入的 N 种姿势,总有一款适合你!
65 2
|
6月前
|
存储 Java 测试技术
Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性
Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性
42 1
java202304java学习笔记第六十天-ssm-spring配置文件-依赖注入6
java202304java学习笔记第六十天-ssm-spring配置文件-依赖注入6
41 0
java202304java学习笔记第六十天-ssm-spring配置文件-依赖注入4
java202304java学习笔记第六十天-ssm-spring配置文件-依赖注入4
61 0
java202304java学习笔记第五十九天员工管理-ssm-spring配置文件-依赖注入2
java202304java学习笔记第五十九天员工管理-ssm-spring配置文件-依赖注入2
52 0
java202304java学习笔记第五十九天员工管理-ssm-spring配置文件-依赖注入3
java202304java学习笔记第五十九天员工管理-ssm-spring配置文件-依赖注入3
45 0
java202304java学习笔记第六十天-ssm-spring配置文件-依赖注入5
java202304java学习笔记第六十天-ssm-spring配置文件-依赖注入5
53 0