【问题标题】:Spring interface injection exampleSpring接口注入示例
【发布时间】:2012-05-02 03:26:48
【问题描述】:

到目前为止,还没有人能够在 Spring Framework 中提供一个正确的接口注入示例。

Martin Fowler 的文章不适用于凡人,其他所有内容都只是以非常混乱的方式定位的文字。我浏览了 30 篇文章,人们要么告诉“Spring 不直接支持接口注入”(“而且因为我不知道我将如何仅描述 setter 和构造函数注入”)或者“我将讨论它”在我的其他线程中”,或者下面很少有 cmets 说这是错误的例子。我不要求解释,例如我BEG。

有三种类型的注入:构造器、设置器和接口。 Spring 不直接支持最新的(正如我观察到的人们所说的那样)。那么具体是怎么做的呢?

谢谢,

【问题讨论】:

  • 您知道,除了“不了解该主题”之外,还可能出于其他原因投反对票。 具体来说,你想要一个例子吗?为您的问题定义“接口注入”。
  • 我猜投反对票是为了回应您的第一段咆哮,而且您的实际问题含糊不清,很容易简化为“有人可以给出 Spring 接口注入的示例吗?我有搜索了几个站点,但还没有找到一个。” (当然,假设这是你的问题)如果你发布你读过的文章也可能会有所帮助,以便人们更好地了解你已经看过的内容。
  • 除了来自@NimChimpsky 的答案(在 Spring 中称为 AutoWiring 并通过 Annotations 或 XML 得到支持),还有一个 SO 问题,其中包含大量关于该主题的资源:@​​987654321@跨度>
  • @Aubergine 我问的是在这个问题的上下文中,接口注入对你来说是什么样的——the Fowler article 对我来说似乎是正常的注入,但通过接口而不是类。如果您正处于撰写论文的阶段,那么 Fowler 的文章似乎应该非常直截了当——它比有关该主题的大多数学术论文更容易阅读,除非您在某种意义上使用“论文”而不是“我正在完成我的博士学位”。
  • 如果将 bsc 最终项目称为论文是冒犯的,我会纠正自己。 :-) 最初我虽然接口注入是当你几乎使用设置器和构造器但提供接口时。下面的例子似乎是同样的混淆,或者我们是正确的。具体来说,这是我唯一难以理解的 Martin Fowler 文章。

标签: java spring dependency-injection interface


【解决方案1】:

根据Variants of DI in spring

DI 存在两种主要的变体,基于构造函数的依赖注入和基于 Setter 的依赖注入。

另请参阅Interface injection is not implemented in Spring 明确说明。

所以只有两种 DI 变体。因此,如果文档没有说明接口注入,很明显它不存在。那些认为接口注入是通过在接口中提供setter方法来完成的人回答我:

  1. 为什么 spring ref doc 没有提到接口注入?
  2. 为什么不能通过提供setter方法接口注入NOT被认为是setter注入本身。为什么要在引入接口不影响任何东西时为此创建特殊术语,我的意思是它仍然以相同的方式配置。如果它们不同,那么如何通过查看配置找到它。在配置中并没有看到实际配置的类实现某些接口的 impl 不应该是透明的吗?
  3. 就像Instantiation using an instance factory methodInstantiation using an static factory method一样,一些bean属性应该明确接口注入?

【讨论】:

  • 在我自己花了相当长的时间解决这个问题之后,我相信 nanosoft 花了足够的精力来反驳其他答案。至少没有证据或示例不会混淆在 Spring IoC 中使用接口和接口注入的 setter/constructor DI。在研究和洞察方面再次做得很好。
【解决方案2】:

通过接口注入,接口明确定义了可以设置依赖项的点:

interface InjectPerson {
    public void injectHere(Person p);
}

class Company implements InjectPerson {
   Person injectedPerson; 

   public void injectHere(Person p) {
        this.injectedPerson = p;
    }
}

【讨论】:

  • 不,注射是在别处完成的。这只是说“一家公司应该能够让一个人注射”。
  • 解决方法不是接口注入-springbyexample.org/examples/…
  • @nanosoft 谢谢,我赞成您的回答,但您提供的资源仍然可以追溯到 Spring 2.0 asfaik。现在我们有了更多的东西,即使当时还没有 Spring Boot 的魔力,我明白为什么他们不能仅仅实现它。我想我将不得不通过 Jira 票直接询问 Spring 家伙,只是出于好奇。
  • @Aubergine - docs.spring.io/spring/docs/current/spring-framework-reference/… 属于春季 4.1.7.RELEASE。您可以通过滚动到页面底部并单击主页链接来检查。在新页面的顶部,您将看到版本 4.1.7.RELEASE。在那个参考文档中,没有提到我在回答中提到的接口注入。
【解决方案3】:

您好,我尝试了一种非常简单的方法,可以澄清您的答案。

以下是我使用两个接口和两个 bean 类构建的代码。

第一个名为 Job 的接口。

public interface Job {
    public void setmyJob(String myJob);
    public String getmyJob();
}

还有一个类来实现这个接口,名称为 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;
    }
}

在下一步中,我创建了另一个名为 Service 的接口

public interface Service {
    public void setJob(Job job);
    public Job getJob();
}

然后另一个类来实现这个服务接口。

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;
    }
}

然后我用main函数在主类上创建并编写代码如下:

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());
    }
}

在我的 Beans.xml 文件中,我提到了如下代码并且它有效。

 <?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>

我也参考了另一个在线教程,然后得到了这种解决方案。如果您对此代码有任何问题,请告诉我。它对我有用。

【讨论】:

  • 你能告诉我你从哪里得到的在线教程吗?
  • 那么它与 setter 注入有何不同...?您在 MyService 类中有属性作业,您本质上是通过 setter 方法注入的,因此是 setter 注入......我相信只是引入接口没有任何区别......
  • Spring 中没有实现接口注入 - springbyexample.org/examples/…
  • 在给定的链接中清楚地写着“这是一种不同类型的 DI,涉及映射项目以注入特定接口。”这意味着我们需要指定为某个接口注入哪个具体实现。我做过类似的事情。注入具体类可能是一种错误的方式,但现在您在类中拥有的是一个包含其具体类引用的接口。
【解决方案4】:

依赖注入有3种类型:-

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 仅支持基于构造函数和设置器的注入。 看起来您对不同的类型(3)和弹簧支持的类型(其中的 2 个)感到困惑。

【讨论】:

    【解决方案5】:

    我认为,关于接口注入的混淆是由于误解了“接口注入”一词的实际含义。在我的理解中,接口注入描述了 bean 竞争者向 bean 注入新接口的能力,不管这个 bean 的类定义没有实现它。

    这里展示的所有示例都展示了如何从具体类中创建一个 bean,然后如何将它注入另一个 bean。事实上,在所有情况下,bean 都被注入到定义为接口的字段中,这并不重要——所有操作都是使用由具体实例创建的 bean 完成的。

    我还可以提供另一个吸引人的例子:

    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>
    

    正如您在此处看到的,甚至可以从接口创建 bean!尽管如此,它不是接口注入,因为 IoC 竞争者自己初始化了这个 bean 的实例。换句话说,card bean 是一个初始化的对象,而不是一个接口,这使得该问题的选择答案是正确的。

    【讨论】:

      【解决方案6】:

      我想有人回答了你的问题here 我也不知道接口注入是什么,直到我从“Pro Spring MVC with web flow book”中阅读了这个声明

      "请注意,Spring 框架不支持基于接口的依赖注入。这个 意味着我们需要指定为某个接口注入哪个具体实现。”

      【讨论】:

        【解决方案7】:

        请查看下面的 iterface 注入示例。

        有一个形状接口和 2 个具体的类来实现形状,即正方形和矩形。

        界面

        package di.interfaceinjection;
        public interface Shape {
            public String shapeName();
            public void displayName();
        }
        

        2 实现类

        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");        
            }
        
        }
        

        现在,我们有一个设置形状的类。

        public class ShapeSetter {
        
            private Shape shape;
        
            public Shape getShape() {
                return shape;
            }
        
            public void setShape(Shape shape) {
                this.shape = shape;
            }
        
        }
        

        最后是配置

        <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>
        

        这里,

        我们正在注入不同的形状。

        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();
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 2011-12-05
          • 2019-04-09
          • 1970-01-01
          • 2012-11-28
          • 2013-11-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多