依赖注入的6种方式

前端之家收集整理的这篇文章主要介绍了依赖注入的6种方式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、Setter注入-Spring

Setter注入是指外部程序通过调用setter方法为客户端注入所依赖的对象。Spring就有采用这种方式。


publicclassClient{
privateService1service1;

publicvoidsetService1(Service1service1){
this.service1=service1;
}

publicvoiddoSomething(){
service1.execute();
}

publicstaticvoidmain(String[]args){
ApplicationContextctx=newClassPathXmlApplicationContext("pattern/part2/chapter6/setter/spring-beans.xml");
Clientclient=(Client)ctx.getBean("client");

client.doSomething();
}
}

配置文件

<beanid="client"class="com.persia.client">
<propertyname="service1"ref="service1"/>
</bean>

mock

publicclassClientTestDrive{
publicvoidtestDoSomething(){
Clientclient=newClient();
MockService1mockService1=newMockService1();
client.setService1(mockService1);

client.doSomething();
assertEquals(mockService1.isExecuted(),true,"TestFailed");
}

publicstaticvoidmain(String[]args){
newClientTestDrive().testDoSomething();
}

privatestaticvoidassertEquals(booleanactual,booleanexpected,Stringmessage){
if(actual!=expected)thrownewIllegalArgumentException(message);
}

privatestaticclassMockService1implementsService1{
privatebooleanexecuted;

publicbooleanisExecuted(){
returnexecuted;
}

@Override
publicvoidexecute(){
executed=true;
}
}
}



二、Constructor注入-PicoContainer

Constructor注入就是通过带参数的构造器注入依赖对象。PicoContainer就是采用这种方式注入的。

publicclassClient{
privateService1service1;

publicClient(Service1service1){
this.service1=service1;
}

publicvoiddoSomething(){
service1.execute();
}

privatestaticMutablePicoContainerconfigure(){
MutablePicoContainerpico=newDefaultPicoContainer();
pico.addComponent(Service1Impl.class);//registeranimplementationofService1
pico.addComponent(Service2Impl.class);
pico.addComponent(Client.class);
returnpico;
}

publicstaticvoidmain(String[]args){
MutablePicoContainerpico=configure();
Clientclient=pico.getComponent(Client.class);
client.doSomething();
}
}

mock

publicclassClientTestDrive{
publicvoidtestDoSomething(){
MockService1mockService1=newMockService1();
Clientclient=newClient(mockService1);

client.doSomething();
assertEquals(mockService1.isExecuted(),Stringmessage){
if(actual!=expected)thrownewIllegalArgumentException(message);
}

privatestaticclassMockService1implementsService1{
privatebooleanexecuted;

publicbooleanisExecuted(){
returnexecuted;
}

@Override
publicvoidexecute(){
executed=true;
}
}
}


三、Annotation注入-Guice

只要接口是@Retention(RUNTIME)的,就可以在运行时期通过反射读取。Annotation注入的方式就是把实例化信息和对象之间的依赖关系信息使用注解的形式表达,只要在运行时期得到它们,就知道如何初始化服务对象了。Guice就是采用这种方式的。注解可以注解在方法、构造器、属性上面。

@ImplementedBy(Service1Impl.class)
publicinterfaceService1{
voidexecute();
}

publicclassClient{
privateService1service1;

@Inject
publicClient(Service1service1){
this.service1=service1;
}

publicvoiddoSomething(){
service1.execute();
}

publicstaticvoidmain(String[]args){
Injectorinjector=Guice.createInjector();
Clientclient=injector.getInstance(Client.class);

client.doSomething();
}
}

mock

publicclassClientTestDrive{
publicvoidtestDoSomething(){
MockService1mockService1=newMockService1();
Clientclient=newClient(mockService1);

client.doSomething();
assertEquals(mockService1.isExecuted(),Stringmessage){
if(actual!=expected)thrownewIllegalArgumentException(message);
}

privatestaticclassMockService1implementsService1{
privatebooleanexecuted;

publicbooleanisExecuted(){
returnexecuted;
}

@Override
publicvoidexecute(){
executed=true;
}
}
}


四、Interface注入-Avalon

客户端通过实现容器/框架所规范的某些特殊接口,在返回这些依赖对象之前,容器回调这些接口方法,注入依赖的服务对象。Apache的Avalon就是采用这种方式注入的。

publicinterfaceServiceAware{
voidinjectService(Serviceservice);
}

publicclassClientimplementsServiceAware{
privateServiceservice;

@Override
publicvoidinjectService(Serviceservice){
this.service=service;
}

publicvoiddoSomething(){
service.execute();
}

publicstaticvoidmain(String[]args){
InterfaceInjector.configure();
Clientclient=InterfaceInjector.getInstance(Client.class);

client.doSomething();
}
}

接口注入

publicclassInterfaceInjector{
privatestaticInterfaceInjectorinjector;
privateMap<Class,Object>services=newHashMap<Class,Object>();

publicstaticvoidconfigure(){
load(newInterfaceInjector());
}

publicstatic<T>TgetInstance(Class<T>clazz){
returninjector.loadService(clazz);
}

privatestaticvoidload(InterfaceInjectorcontainer){
InterfaceInjector.injector=container;
}

@SuppressWarnings("unchecked")
private<T>TloadService(Class<T>clazz){
Objectservice=injector.services.get(clazz);
if(service!=null){
return(T)service;
}

try{
service=clazz.newInstance();
if(serviceinstanceofServiceAware){
((ServiceAware)service).injectService(newServiceImpl());
}
injector.services.put(clazz,service);
}catch(InstantiationExceptione){
e.printStackTrace();
}catch(IllegalAccessExceptione){
e.printStackTrace();
}
return(T)service;
}
}

mock

publicclassClientTestDrive{
publicvoidtestDoSomething(){
MockServicemockService=newMockService();
Clientclient=newClient();
client.injectService(mockService);

client.doSomething();
assertEquals(mockService.isExecuted(),Stringmessage){
if(actual!=expected)thrownewIllegalArgumentException(message);
}

privatestaticclassMockServiceimplementsService{
privatebooleanexecuted;

publicbooleanisExecuted(){
returnexecuted;
}

@Override
publicvoidexecute(){
executed=true;
}
}
}


五、Parameter注入

外部程序通过函数参数,给客户端注入所依赖的服务对象。构造器注入和setter注入都可以看成是参数注入的变形。

publicclassClient{
publicvoiddoSomething(Serviceservice){
service.execute();
}

publicstaticvoidmain(String[]args){
//createaservice
Serviceservice=newServiceImpl();

//putnew-createdserviceinstancebyinputparameter
newClient().doSomething(service);
}
}

mock

publicclassClientTestDrive{
publicvoidtestDoSomething(){
MockServicemockService=newMockService();
Clientclient=newClient();

client.doSomething(mockService);
assertEquals(mockService.isExecuted(),Stringmessage){
if(actual!=expected)thrownewIllegalArgumentException(message);
}

privatestaticclassMockServiceimplementsService{
privatebooleanexecuted;

publicbooleanisExecuted(){
returnexecuted;
}

@Override
publicvoidexecute(){
executed=true;
}
}
}


六、其他形式的注入

诸如Guice使用的Providers的注入方式等。


小结:依赖注入的好处:把实例化的过程交给框架/容器来处理,这样可以更专注于业务逻辑的开发。Setter和Contructor注入是常见的注入方式。


摘自《漫谈设计模式》

猜你在找的设计模式相关文章