概念:
依赖注入一词让人望而生畏,但现在已经演变成复杂的编程技巧或设计模式理念.
在项目中应用DI(Dependency Injection, DI),可以使代码更容易理解和测试.
DI功能是如何实现的:
一个应用都会由多个类组成,每个对象负责管理与自己相互协作的对象的引用,这样会使代码高度耦合和难以测试.
举个类似的例子:
package main.java;
/**
* @author myvina@qq.com
* @date 18-4-14 下午7:51
*/
public class Demo1{
private Test test;
public Demo1(){
test = new Test;
}
public void doSomthing(){
test.doSomething();
}
}
Demo1类的构造器中自行创建了一个Test对象,使得Test和Demo1紧密的耦合在一起,让我们编写单元测试变得困难.
耦合具有两面性.一方面,紧密耦合的代码难以测试,复用和理解;但另一方面,一定程度的耦合是必须的.
通过DI,对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定.对象无需自行创建或
管理它们的依赖关系,依赖关系将被自动注入到需要它们的对象中去.
例子如下:
package main.java;
/**
* @author myvina@qq.com
* @date 18-4-14 下午7:51
*/
public class Demo1{
private Test test;
public Demo1(Test test){
this.test = test;
}
public void doSomthing(){
test.doSomething();
}
}
不同于之前代码,Demo1对象没有自行创建Test对象,而是在执行构造函数的时候将Test对象作为参数传入,这就是以来注入的方式之一,即构造器注入(constructor injection).
如果Test是一个接口,则Demo1对象能调用任何实现Test接口类对象的doSomething方法.
这就是DI所带来的最大收益--松耦合.如果一个对象只通过结构来表明依赖关系,那么这种以来就能够在对象本身毫不知情的情况下用不同的具体实现类进行替换.
Spring中依赖注入:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--默认使用的Bean是单例模式--> <!--加上属性scope="prototype",则每次从容器获取的bean都是新对象--> <!--当bean的作用域为prototype时,bean对象并不会在Spring容器启动时就进行创建--> <!--当为默认方式时,bean对象是在Spring容器启动时就进行创建了即默认情况下会--> <!--在容器启动时初始化bean,但我们也可以指定bean节点的属性lazy-init=“true”来--> <!--延迟初始化bean,这时候,只有第一次获取bean会才初始化bean--> <!--如果想对所有bean都应用延迟初始化,可以在根节点beans设置default-lazy-init="true"--> <!--当配置属性init-method="init"时,当Spring容器实例化对象时,就执行该对象的init()(任意起名)方法--> <!--当配置属性destroy-method="destroy"时,当Spring容器实例化对象时,就执行该对象的destroy()方法--> <!--第一种依赖注入的方法--> <bean id="personDao" class="com.vina.java.beans.implement.PersonDaoBean"/> <bean id="personService" class="com.vina.java.beans.implement.PersonServiceBean" > <!--引用其他对象时的依赖注入--> <property name="personDao" ref="personDao"/> <!-- 为基本类型属性注入值(bean中暂时没写这两个属性) --> <!--<property name="name" value="itcast" />--> <!--<property name="id" value="88" />--> </bean> <!--第二种依赖注入的方式,只是内部bean不能被其他bean使用--> <!--<bean id="personService" class="com.vina.java.beans.implement.PersonServiceBean">--> <!--<property name="personDao">--> <!--<bean class="com.vina.java.beans.implement.PersonDaoBean"/>--> <!--</property>--> <!--</bean>--> </beans>
Spring简单应用:
package com.vina.junit.test;
import com.vina.java.beans.PersonService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeansTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/vina/config/beans/beans.xml");
PersonService personService1 = (PersonService)ctx.getBean("personService");
PersonService personService2 = (PersonService)ctx.getBean("personService");
System.out.println(personService1 == personService2);
personService1.save();
((ClassPathXmlApplicationContext) ctx).close();
}
}