且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

用spring注入匿名类

更新时间:2023-01-11 10:48:46

好,我的用例的最终解决方案将使用这个答案.这样做会更好,因为可以跟踪使用情况,并且摆脱了当前方法所遇到的每个问题.

Ok, final solution for my use case will use the approach described in this answer. It would be better because it will be possible to track usages and I'll get rid of every problem I'm having with the current approach.

这样,我可以执行以下操作

In that way I can do the following

@Component
public class ArtifactImpl extends AbstractGenericImpl<Artifact> {
}

@Component
public class MaterialImpl extends AbstractGenericImpl<Material> {
}

@Component
class Usage {
  @Autowired ArtifactImpl foo;
  @Autowired MaterialImpl bar;
}

通过这种方式,所有内容都在编译时进行了检查,实际上我摆脱了Class<T>构造函数,并且已经进行了自动装配(没有@Qualifier),并且下面的测试有效:

In this way everything is checked at compile time and I got rid of Class<T> constructor in fact I have autowiring in place (without @Qualifier) and the following test is working:

@RunWith(SpringJUnit4ClassRunner.class)
public class AutowiringTest {
  @Autowired Usage test;

  public void testAutowiring() {
    assertThat(test.foo.getGenericType(), equalTo(Artifact.class));
    assertThat(test.bar.getGenericType(), equalTo(Material.class));
  }
}

原始答案

好吧,我发现我要问的是没有用的,因为自动装配在运行时发生,因此具有两个不同对象的自动装配对象会导致弹簧错误,即,这是行不通的:

Original answer

Ok, I've found out that what I'm asking will be useless because autowiring happens at runtime and so having two autowired object with different objects will lead to spring errors, i.e. this won't work:

@Configuration
class RetrieverProvider {
    @Bean 
    Retriever<Artifact> getArtifact() {
        return new RetrieverImpl<Artifact>() {};
    }

    @Bean 
    Retriever<Material> getMaterial() {
        return new RetrieverImpl<Material>() {};
    }
}

class InjectedAttempt {
    // at injection time, i.e. runtime, type erasure prevent spring to distinguish
    @Autowired Retriever<Artifact> foo; // this type
    @Autowired Retriever<Material> bar; // from this type
    // so it cannot perform injection by type
}

唯一可行的方法就是以这种方式使用限定符,但是我不喜欢这种方法,因此我将继续使用xml配置和构造函数参数.

The only way to get that working is to use qualifiers in this way, but I don't like this approach, so I'll remain with xml configuration and constructor arguments.

@Configuration
class RetrieverProvider {

    @Bean @Qualifier("artifact") Retriever<Artifact> getArtifact() {
        return new RetrieverImpl<Artifact>() {};
    }

    @Bean @Qualifier("material")
    Retriever<Material> getMaterial() {
        return new RetrieverImpl<Material>() {};
    }


}

class Injected {

    @Autowired @Qualifier("artifact") Retriever<Artifact> foo;

    @Autowired @Qualifier("material") Retriever<Material> bar;
}

作为旁注, guice支持通用注射,也许spring也有类似的用法.

As a side note guice has support for generic injections, maybe spring has something similar.