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的实现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
控制反转(Inversion of Control,简称IoC)和依赖注入(Dependency Injection,简称DI)是两个相关的概念,用于解耦和管理对象之间的依赖关系。 控制反转(IoC)是一种设计原则,它将对象的创建和管理权从应用程序代码中转移到容器中。传统的程序设计中,对象之间的依赖关系由对象自己创建和管理,而在IoC中,容器负责创建和管理对象,并将它们注入到需要它们的地方。 依赖注入(DI)是实现IoC的一种方式。它通过将依赖关系作为参数传递给对象,或者通过使用容器来自动注入依赖关系,来实现对象之间的解耦。依赖注入可以通过构造函数注入、属性注入或者接口注入等方式来实现。 下面是一个简单的示例来说明IoC和DI的概念: 假设我们有一个UserService类,它依赖于一个UserRepository类来获取用户数据。在传统的程序设计中,UserService需要自己创建UserRepository对象并管理它的生命周期: ```java public class UserService { private UserRepository userRepository; public UserService() { userRepository = new UserRepository(); } public User getUserById(int id) { return userRepository.getUserById(id); } } ``` 而在使用IoC和DI的方式下,我们可以将UserRepository的创建和管理交给容器来处理,UserService只需要声明它所依赖的UserRepository,并通过构造函数或者属性注入的方式接收它: ```java public class UserService { private UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public User getUserById(int id) { return userRepository.getUserById(id); } } ``` 在这个示例中,UserService不再负责创建UserRepository对象,而是通过构造函数接收一个UserRepository对象。这样,我们可以通过容器来创建UserService,并将一个UserRepository对象注入到它中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值