Spring接口注入示例

Posted

技术标签:

【中文标题】Spring接口注入示例【英文标题】:Spring interface injection example 【发布时间】: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 文章。 【参考方案1】:

根据Variants of DI in spring

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

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

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

    为什么 spring ref doc 没有提到接口注入? 为什么不能通过提供setter方法接口注入NOT被认为是setter注入本身。为什么要在引入接口不影响任何东西时为此创建特殊术语,我的意思是它仍然以相同的方式配置。如果它们不同,那么如何通过查看配置找到它。在配置中并没有看到实际配置的类实现某些接口的 impl 不应该是透明的吗? 就像Instantiation using an instance factory method和Instantiation 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();
    


【讨论】:

以上是关于Spring接口注入示例的主要内容,如果未能解决你的问题,请参考以下文章

Spring(SpringBoot)--同类型多个bean的注入--@Primary/@Qualifier

feign接口注入失败问题

spring不用注入注解怎么接口所有实现类bean

Spring接口编程_设值注入和构造注入

分享Spring中接口注入的三种方式

接口的Spring依赖注入