可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
No one so far was capable of providing a working correct example of interface injection in Spring Framework. Martin Fowler article is not for mortals, everything else just words positioned in a very confusing way. I have surfed over THIRTY articles, where people either tell "Spring doesnt directly supports for interface injection"("and because I don't know exactly how I will only describe setter and constructor injections") or either "I will discuss it in my other threads" or either there will be few comments below saying that it is wrong example. I don't ask for explanation, I BEG for example.
There are three types of injection: Constructor, Setter and Interface. Spring doesn't support the latest directly(as I have observed people saying). So how is it done exactly?
Thank You,
回答1:
According to Variants of DI in spring
DI exists in two major variants, Constructor-based dependency injection and Setter-based dependency injection.
Also see Interface injection is not implemented in Spring clearly states it.
So there are only two variants of of DI. So if documentation says nothing about interface injection, its clear that its not there. Those who believe that interface injection is done by providing setter method in interface answer me:
- Why spring ref doc left mention of interface injection?
- Why cann't interface injection via providing setter method NOT considered as setter injection itself. Why create special term for that when introduction of interface doesn't affect anything, I mean its still configured the same way. If they were different then how can one find it via seeing the config. Shouldn't it be transparent that in config and not seeing the impl that actually configured class implements some interface ?
- Just like Instantiation using an instance factory method and Instantiation using an static factory method, some bean attributes should clarify the interface injection?
回答2:
With interface injection an interface explicitly defines the point where a dependency can be set:
interface InjectPerson {
public void injectHere(Person p);
}
class Company implements InjectPerson {
Person injectedPerson;
public void injectHere(Person p) {
this.injectedPerson = p;
}
}
回答3:
Hi I tried with a very simple approach that may clarify your answer.
following is the code that i have built on using two interfaces and and two bean classes.
first interface with name Job.
public interface Job {
public void setmyJob(String myJob);
public String getmyJob();
}
and one class to implement this interface with name as MyJob
public class MyJob implements Job {
public String myJob;
public MyJob() {
System.out.println("From MyJob default Constructor and the ID= "+this);
}
public void setmyJob(String myJob) {
this.myJob=myJob;
}
public String getmyJob() {
return myJob;
}
}
In the next step i created another Interface with name as Service
public interface Service {
public void setJob(Job job);
public Job getJob();
}
and then again another class to implement this Service Interface.
public class MyService implements Service {
public Job job;
public void setJob(Job job) {
this.job=job;
System.out.println("Hello from Myservice: Job ID="+job);
}
public Job getJob() {
return job;
}
}
then i created on main class with the main function and written the code as follows:
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApplication {
public static void main(String...a) {
BeanFactory beanfactory=new ClassPathXmlApplicationContext("Beans.xml");
MyService myservice=(MyService)beanfactory.getBean("myservice");
System.out.println("Before print");
System.out.println(myservice.getJob().getmyJob());
}
}
in my Beans.xml file i mentioned the code as follows and it worked.
<?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-3.0.xsd">
<bean id="myjob" class="MyJob">
<property name="myJob" value="My First String"/>
</bean>
<bean id="myservice" class="MyService">
<property name="job" ref="myjob"/>
</bean>
</beans>
I have also reffered to another online tutorials and then got this kind of solution. please let me know if you have any problem with this code. it is working for me.
回答4:
There are 3 types of dependency injections:-
1. Constructor Injection(E.g Pico Container, Spring supports it).
2. Setter Injection(E.g Spring supports it).
3. Interface Injection(E.g Avalon, Spring does not support it).
Spring supports only constructor and setter based injection.
Looks like you got confused in the different types(3) and what spring supports(2 of them).
回答5:
I think someone answered your questions here
I also didn't know what Interface injection is until I read this statement from "Pro Spring MVC with web flow book"
"Note that interface-based dependency injection isn’t supported by the Spring Framework. This
means that we need to specify which concrete implementation to inject for a certain interface."
回答6:
Please check the below example for iterface injection.
There is a shape interface and 2 concrete classes which imiplements shape namely square and rectangle.
The interface
package di.interfaceinjection;
public interface Shape {
public String shapeName();
public void displayName();
}
2 Implemented classes
package di.interfaceinjection;
public class Square implements Shape {
@Override
public String shapeName() {
return "Square";
}
@Override
public void displayName() {
System.out.println("Square");
}
}
package di.interfaceinjection;
public class Rectangle implements Shape{
@Override
public String shapeName() {
return "Rectangle";
}
@Override
public void displayName() {
System.out.println("Rectangle");
}
}
Now, we have a class which sets the shape.
public class ShapeSetter {
private Shape shape;
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
}
and finally the configuration
<bean id="shape1" class="di.interfaceinjection.ShapeSetter">
<property name="shape" ref="square"></property>
</bean>
<bean id="shape2" class="di.interfaceinjection.ShapeSetter">
<property name="shape" ref="rectangle"></property>
</bean>
<bean id="square" class="di.interfaceinjection.Square"></bean>
<bean id="rectangle" class="di.interfaceinjection.Rectangle"></bean>
Here,
we are injecting different shapes.
package di.interfaceinjection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class InterfaceInjeection {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("intro.xml");
ShapeSetter shape = (ShapeSetter)appContext.getBean("shape2");
shape.getShape().displayName();
}
}
回答7:
I think, that the confusion around interface injection is caused by missunderstanding what the term "interface injection" actually means. In my understanding, interface injection describes the ability of a bean contener to inject a new interface to the bean, no matter that the class definition of this bean is not implementing it.
All examples presented here show how to create a bean out of concrete class, and then how to inject it into another bean. The fact, that in all cases bean is injected into a field defined as an interface does not matter- all operations are done with beans created out of concrete instances.
I can provide also another catchy example:
package creditCards;
interface PaymentCard {
Boolean isDebitAllowed();
}
<bean id="card" class="creditCards.PaymentCard">
<lookup-method name="isDebitAllowed" bean="boolValue"/>
</bean>
<bean id="boolValue" class="java.lang.Boolean">
<constructor-arg type="boolean" value="true"/>
</bean>
As you see here, it is even possible to create a bean out of interface! Still, it is not a interface injection, as IoC contener initializes instanse of this bean by its own. In other words, card
bean is an initialized object, not an interface, what makes, that the selected answer for this question is correct.