2017-08-22 119 views
0

我有這樣的一種方式的接口:春季啓動管理界面豆類

public interface Vehicle<T> { 
    void stuff(T param); 
} 

@Component 
public class Car<T> implements Vehicle<T> { 
    private final Strategy<T> strat; 

    public Car(@Lazy Strategy strat) { 
     this.strat = strat; 
    } 

    void stuff(T param) { 
     strat.stuff(param); 
    } 
} 

策略接口/類看起來是這樣的:

public interface Strategy<T> { 
    void stuff(T param); 
} 

@Component 
public class FooAStrategy implements Strategy<FooA> { 
    void stuff(FooA param) { //do stuff } 
} 

@Component 
public class FooBStrategy implements Strategy<FooB> { 
    void stuff(FooABparam) { //do stuff } 
} 

最後,我有這樣的服務類:

@Service 
public class ServiceClassA { 
    private FooA fooA; 
    private FooB fooB; 
    private FooC fooC; 
    private Vehicle<FooD> vehicle; //how to inject correct implementation? 

    public ServiceClass(FooA fooA, FooB fooB, FooC fooC) { 
     this.fooA = fooA; 
     this.fooB = fooB; 
     this.fooC = fooC; 
    } 
} 

@Service 
public class ServiceClassB { 
    private FooA fooA; 
    private FooB fooB; 
    private FooC fooC; 
    private Vehicle<FooE> vehicle; //how to inject correct implementation? 

    public ServiceClass(FooA fooA, FooB fooB, FooC fooC) { 
     this.fooA = fooA; 
     this.fooB = fooB; 
     this.fooC = fooC; 
    } 
} 

本質上,對於第一個服務類,ServiceClassA,我想要做的這樣的:

Strategy strat = new FooAStrategy(); 
Vehicle vehicle = new Car(strat); 
ServiceClassA class = new ServiceClassA(fooA, fooB, fooC, vehicle); 

但每次我運行應用程序時我得到這個錯誤:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.test.notification.Strategy<?>' available: expected single matching bean but found 2: fooAStrategy,fooBStrategy 
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116) 
    at org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver$1.getTarget(ContextAnnotationAutowireCandidateResolver.java:83) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192) 
    at com.sun.proxy.$Proxy259.generateNotifications(Unknown Source) 
    at com.test.notification.RabbitMQEventPublisher.process(RabbitMQEventPublisher.java:24) 
    at com.test.services.ServiceClassA.testConncetion(ServiceClassA.java:400) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 
    at com.sun.proxy.$Proxy260.testConnection(Unknown Source) 
    at com.test.controllers.ControllerTest.get(ControllerTest.java:130) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at com.test.security.jwt.JwtTokenAuthenticationProcessingFilter.successfulAuthentication(JwtTokenAuthenticationProcessingFilter.java:52) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:240) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) 
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) 
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 

由於我使用的是@Component註釋和構造我沒有讓春天啓動線的一切行動本身有任何配置類。我不知道如何指定1依賴的具體實現。

什麼是最好的方式去做這件事?

+1

它似乎在重複這裏:https://開頭計算器.com/questions/22300102/no-unique-bean-of-type-is-defined-expected-single-matching-bean-but-found-2 –

+0

@KennyTaiHuynh我知道它爲什麼會發生,我想知道解決方案這個問題是。 – Richard

回答

0

從汽車中取出@Component並注入工廠。就像這個消息所說的那樣,Spring對於需要創建的東西是不明確的。一種解決方案是通過工廠自己創建汽車,例如FooACarFactory(可實施通用FooAVehicleFactory)。您可以讓Spring創建FooACarFactory並將其注入到具有vehicle = fooAVehicleFactory.create()的服務構造函數中。注意:如果組件掃描路徑中同時有FooACarFactoryFooATruckFactory,則可以使用@Kenny提到的@Primary註釋強制Spring注入所需的注入。或者,將正確實現的jar放在java類路徑中。

或者,而不是製造汽車廠的變化,你可以有一個通用的工廠:

@Component 
public class VehicleFactory { 

    @Autowired 
    FooAStrategy fooAStrategy; 

    @Autowired 
    FooBStrategy fooBStrategy; 

    boolean buildTruck = true; //get from external system parameter instead 

    public <T> Vehicle<T> getObject(Class<?> clazz) throws Exception { 
     if (clazz.equals(FooA.class)) { 
      if (buildTruck) { 
       return (Vehicle<T>) new Truck<FooA>(fooAStrategy); 
      } 
      return (Vehicle<T>) new Car<FooA>(fooAStrategy); 
     } 
     return (Vehicle<T>) new Car<FooB>(fooBStrategy); 
    } 

然後在服務類:

@Service 
public class ServiceClassA { 
    private FooA fooA; 
    private FooB fooB; 
    private Vehicle<FooA> vehicle; 

    @Autowired 
    public ServiceClassA(
      FooA fooA, FooB fooB, 
      CarFactory vehicleFactory 
      ) throws Exception { 
     this.fooA = fooA; 
     this.fooB = fooB; 
     this.vehicle = vehicleFactory.<FooA>getObject(FooA.class); 
    } 
} 
+0

這究竟會如何工作?我會爲每種車型和戰略類型建立一個工廠嗎?像'FooACarFactory','FooBCarFactory','FooATruckFactory'等等。 – Richard

+0

是的,但有優化,例如。通過操作Spring配置來創建不同的bean集合,以便基於路徑中的jar文件進行注入。或者通過一個通用工廠查看我的手動編輯方式。 –

-1

作爲您的評論,我想更正答案。這也是同樣的想法。使用@Primary,@Component@Resource

@Primary 
@Component("car") 
public class Car<T> implements Vehicle<T> { 
//... 
} 

在服務使用車輛,某事的樣子:

@Service 
public class ServiceClassA { 
    private FooA fooA; 
    private FooB fooB; 
    private FooC fooC; 

    @Resource(name="car") 
    private Vehicle<FooA> vehicle; 

... 
} 

@Primary 
@Component("fooAStrategy") 
public class FooAStrategy implements Strategy<FooA> { 
} 

@Component("fooBStrategy") 
public class FooBStrategy implements Strategy<FooB> { 
} 

希望這有助於。

+0

這不是我想要的。請再看一下原來的帖子。我不能只注入戰略。服務類通過Vehicle界面定義策略的類型。 – Richard

+0

@Richard:只需在答案中添加一些代碼,你可以試試?! –

+0

不,這不起作用。問題不在於Car這個對象,而在於定義策略。給汽車一個組件名稱在這方面沒有幫助 – Richard