依赖注入定义:
组件依赖于抽象,当组件要与具体实现类产生依赖,则通过抽象注入实际对象。组件和具体实现类的关系由抽象进行中转。
XXX 注入 XXX
注入具体实现类
通过抽象注入具体实现类。
依赖注入的三种方式:
1、接口注入:一般定义一个接口,逻辑类实现该接口和该接口定义的方法, 在必须实现的方法中通过抽象类注入具体实现类。
2、set注入:通过set方法,set某一个具体实现类,或者在xml配置文件中配置。
3、构造器注入:在接受注入的类中定义一个构造方法,并在参数中定义需要注入的元素。构造器注入的xml配置和set注入有写区别。
详细说明各种注入:
(一)接口注入:
1、具体类的抽象类
2、具体实现类
3、注入类(注入类接口,注入类实现接口的方法)
4、测试类,new一个注入类,调用实现的方法。
实例代码:
具体类的抽象类
package com.gc.impl;
//编写接口,实现依赖抽象
public interface DataBase {
public abstract void getDataBase();
}
实现具体类
package com.gc.acion;
import com.gc.impl.DataBase;
public class OracleDataBase implements DataBase{
@Override
public void getDataBase() {
// TODO Auto-generated method stub
//oracle获取数据的方法
}
}
package com.gc.acion;
import com.gc.impl.DataBase;
public class DB2DataBase implements DataBase{
@Override
public void getDataBase() {
// TODO Auto-generated method stub
//db2获取数据的方法
}
}
定义注入类接口,所有实现该接口的类都必须实现抽象方法,从而达到注入的目的。
package com.gc.impl;
//接口注入,通过实现该接口中所有的方法,给所有实现该接口的类都注入了DataBase的实现类
public interface IDataBaseBusinnes {
public abstract void creatDI(DataBase dataBase);
}
注入类的实现
package com.gc.acion;
import com.gc.impl.DataBase;
import com.gc.impl.IDataBaseBusinnes;
//业务逻辑层,获取数据时通过接口进行编程,而不是具体类(实现依赖抽象即业务逻辑实现类通过抽象的接口去编写,而不是抽象依赖实现)
public class DataBaseBusinnes implements IDataBaseBusinnes{
private DataBase dataBase = null;
//根据注入的数据库类获取具体的数据库数据
public DataBase getDataBase(){
return dataBase;
}
//接口注入
@Override
public void creatDI(DataBase dataBase) {
// TODO Auto-generated method stub
}
}
测试类:
new DataBaseBusinnes
package com.gc.test;
import com.gc.acion.DataBaseBusinnes;
import com.gc.acion.OracleDataBase;
public class DataBaseTest {
public static void main(String[] args) {
DataBaseBusinnes dbbussinnes = new DataBaseBusinnes();
//接口注入
dbbussinnes.creatDI(new OracleDataBase());
dbbussinnes.getDataBase();
}
}
(二)set注入:
可以通过配置文件注入也可以不通过配置文件注入:
具体实现类的抽象类:
package com.gc.impl;
//编写接口,实现依赖抽象
public interface DataBase {
public abstract void getDataBase();
}
具体实现类:
package com.gc.acion;
import com.gc.impl.DataBase;
public class OracleDataBase implements DataBase{
@Override
public void getDataBase() {
// TODO Auto-generated method stub
//oracle获取数据的方法
}
}
package com.gc.acion;
import com.gc.impl.DataBase;
public class DB2DataBase implements DataBase{
@Override
public void getDataBase() {
// TODO Auto-generated method stub
//db2获取数据的方法
}
}
注入类:通过set方法抽象注入DataBase
package com.gc.acion;
import com.gc.impl.DataBase;
//业务逻辑层,获取数据时通过接口进行编程,而不是具体类(实现依赖抽象即业务逻辑实现类通过抽象的接口去编写,而不是抽象依赖实现)
public class DataBaseBusinnes{
private DataBase dataBase = null;
//根据注入的数据库类获取具体的数据库数据
public DataBase getDataBase(){
return dataBase;
}
//set注入
public void setDataBase(DataBase dataBase){
this.dataBase = dataBase;
}
}
测试类:set注入
dbbussinnes.setDataBase(new OracleDataBase());
package com.gc.test;
import com.gc.acion.DataBaseBusinnes;
import com.gc.acion.OracleDataBase;
public class DataBaseTest {
public static void main(String[] args) {
DataBaseBusinnes dbbussinnes = new DataBaseBusinnes();
dbbussinnes.setDataBase(new OracleDataBase());
dbbussinnes.getDataBase();
}
}
有一种情况是
dbbussinnes.setDataBase(new OracleDataBase());
set方法是不要的,在配置文件里给DataBase指向具体的实现得到bean,再通过这个bean类的方法getDataBase();
这种就是通过配置文件注入,更方便
(三)构造函数注入
可以通过配置文件的方法注入和不通过配置文件的方式注入
具体实现类的抽象类
package com.gc.impl;
//编写接口,实现依赖抽象
public interface DataBase {
public abstract void getDataBase();
}
具体实现类
package com.gc.acion;
import com.gc.impl.DataBase;
public class OracleDataBase implements DataBase{
@Override
public void getDataBase() {
// TODO Auto-generated method stub
//oracle获取数据的方法
}
}
package com.gc.acion;
import com.gc.impl.DataBase;
public class DB2DataBase implements DataBase{
@Override
public void getDataBase() {
// TODO Auto-generated method stub
//db2获取数据的方法
}
}
注入类
package com.gc.acion;
import com.gc.impl.DataBase;
//业务逻辑层,获取数据时通过接口进行编程,而不是具体类(实现依赖抽象即业务逻辑实现类通过抽象的接口去编写,而不是抽象依赖实现)
public class DataBaseBusinnes{
private DataBase dataBase = null;
//构造函数
public DataBaseBusinnes(DataBase dataBase){
this.dataBase = dataBase;
}
//根据注入的数据库类获取具体的数据库数据
public DataBase getDataBase(){
return dataBase;
}
}
测试类
package com.gc.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.gc.acion.DataBaseBusinnes;
import com.gc.acion.OracleDataBase;
public class DataBaseTest {
public static void main(String[] args) {
//不通过配置文件的方式注入
//DataBaseBusinnes dbbussinnes = new DataBaseBusinnes(new OracleDataBase());
//通过配置文件的方式注入
ApplicationContext context = new FileSystemXmlApplicationContext("config.xml");
DataBaseBusinnes dbbussinnes = (DataBaseBusinnes)context.getBean("DataBase");
dbbussinnes.getDataBase();
}
}
构造函数的xml配置:
<!-- 构造函数注入 ,constructor-arg表示通过构造函数注入的方式注入,index="0"表示构造函数的第一个参数,如果只有一个参数可省略-->
<bean id="DataBase" class="com.gc.acion.OracleDataBase">
<constructor-arg index="0">
<value>OracleDataBase</value>
</constructor-arg>
</bean>
以上三种方式的不同均在注入类的注入方式不同,有通过接口的,有通过set方法的,有通过构造函数的。
关于选用哪种注入方式的问题,构造注入是在对象创建时期就完成注入,set注入的方式是在创建对象完成后进行注入。一般使用set注入会稍微多一些。