简体   繁体   English

如何自动连接实现接口

[英]How to Autowire Interface with Implementation

I have been Googling the answer for a long time, but I am certain I am missing something that would bring this all together. 我已经搜寻了很长时间的答案,但是我可以肯定我错过了一些可以将所有这些结合在一起的东西。 I am just not sure what. 我只是不确定。 It is failing on running the Spring server with error: 运行Spring服务器失败,并显示以下错误:

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.abc.sv.dao.TestDAO com.test.abc.sv.controller.TestController.testDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.abc.sv.dao.TestDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:293)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1186)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
    at com.test.abc.sv.SpringLaunch.main(SpringLaunch.java:26)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.abc.sv.dao.TestDAO com.test.abc.sv.controller.TestController.testDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.abc.sv.dao.TestDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:509)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:290)
    ... 16 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.abc.sv.dao.TestDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1118)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:967)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:481)
    ... 18 common frames omitted

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.abc.sv.dao.TestDAO com.test.abc.sv.controller.TestController.testDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.abc.sv.dao.TestDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:293)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1186)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
    at com.test.abc.sv.SpringLaunch.main(SpringLaunch.java:26)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.abc.sv.dao.TestDAO com.test.abc.sv.controller.TestController.testDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.abc.sv.dao.TestDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:509)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:290)
    ... 16 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.abc.sv.dao.TestDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1118)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:967)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:481)
    ... 18 more

So I am running the application from SpringLaunch.class - com.test.abc.sv 所以我从SpringLaunch.class - com.test.abc.sv运行该应用程序

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class SpringLaunch extends SpringBootServletInitializer{

public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(applicationClass);
}

private static Class<SpringLaunch> applicationClass = SpringLaunch.class;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUrl("jdbc:oracle:thin:@(DESCRIPTION ="
                                            +"(LOAD_BALANCE=on)"
                                            +"(FAILOVER=on)"
                                            +"(ADDRESS=(PROTOCOL=tcp)(HOST=56.276.152.217)(PORT=1521))"
                                            +"(ADDRESS=(PROTOCOL=tcp)(HOST=56.276.152.218)(PORT=1521))"
                                            +"(CONNECT_DATA=(SERVICE_NAME=test.abc.com)))");
        dataSource.setUsername("DevUser");
        dataSource.setPassword("Credential");

        return dataSource;
    }

    @Bean
    public TestDAO testDAO() {
        return new TestDAOImpl(dataSource());
    }

} }

TestController.class - com.test.abc.sv.controller

    @RestController
@RequestMapping("/test")
public class TestController{


    @Autowired
    TestDAO testDao;

    final static Logger logger = Logger.getLogger(TestController.class);

    @RequestMapping(value="/setup", method = RequestMethod.GET)
    public Message setupTest(@RequestParam(value="id", required=true) String testNumber) {
        String testMsg = new String(); 

        try{
            testMsg = testDao.prepDatabase(testNumber);
        }
        catch(SQLException e)
        {
            //Log e.getMessage();
            logger.error(e.getMessage());
            System.out.println(e.getMessage());
            return new Message("-1");
        }

        return new Message(testMsg);
    }

    @RequestMapping(value="/teardown", method = RequestMethod.GET)
    public Message teardownTest(@RequestParam(value="id", required=true) String testNumber) {
        String testMsg = new String(); 

        try{
            testMsg = testDao.removeTestData(testNumber);
        }
        catch(SQLException e)
        {
            //Log e.getMessage();
            logger.error(e.getMessage());
            System.out.println(e.getMessage());
            return new Message("-1");
        }

        return new Message(testMsg);
    }

}

TestDAO.class - com.test.abc.sv.dao Interface TestDAO.class - com.test.abc.sv.dao接口

 public interface TestDAO {

    public String prepDatabase(String testNumber)
            throws SQLException;

    public String removeTestData(String testNumber)
            throws SQLException;

}

`TestDAOImpl.class - com.test.abc.sv.dao' `TestDAOImpl.class-com.test.abc.sv.dao'

    @Component
public class TestDAOImpl implements TestDAO{

    private Log log = LogFactory.getLog(TestDAOImpl.class);

    private JdbcTemplate jdbcTemplate;

    public TestDAOImpl(DataSource dataSource) {
        jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public String prepDatabase(String testNumber)
            throws SQLException {

        //Impl Stuff

    }

    @Override
    public String removeTestData(String testNumber)
            throws SQLException {

        //Impl Stuff
    } 

}

From the documentation of @ComponentScan : @ComponentScan文档中:

If specific packages are not defined scanning will occur from the package of the class with this annotation. 如果未定义特定的程序包,将使用带有此批注的类的程序包进行扫描。

Your Application class is in com.test.abc.sv.controller package according to your question. 根据您的问题, Application类位于com.test.abc.sv.controller程序包中。 So everything in com.test.abc.sv.controller and its subppackages will be scanned, but that doesn't include your custom configuration or services because they are not in supbackages of com.test.abc.sv.controller . 因此,将扫描com.test.abc.sv.controller及其子程序包中的所有内容,但这不包括您的自定义配置或服务,因为它们不属于com.test.abc.sv.controller

So the solution would be to move the Application class to for example com.test.abc package or explicitly define the package to scan as com.test.abc for instance. 因此,解决方案是将Application类移至例如com.test.abc包,或显式定义要扫描为com.test.abc的包。

Also I'm not really sure why are you using that custom configuration class. 我也不太确定为什么要使用该自定义配置类。 You can configure data source using Spring Boot properties . 您可以使用Spring Boot属性配置数据源。

And as for the DAO/service bean declarations in your configuration class, that's what the @Service or @Repository annotation for service and dao respectively are for. 对于配置类中的DAO / service bean声明,分别是用于service和dao的@Service@Repository批注。 So I would suggest getting rid of those too. 因此,我建议也摆脱这些。 If you don't you will most likely get another exception, because your beans will be registered once by the component scan and second time from your configuration class, which will result in NoUniqueBeanDefinitionException . 如果您不这样做,则很可能会遇到另一个异常,因为组件扫描将一次注册Bean,第二次从配置类中注册您的bean,这将导致NoUniqueBeanDefinitionException

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何@autowire实现在xml文件中的接口(Jersey + Spring) - How to @autowire an interface whose implementation is in the xml file (Jersey + Spring) 如何在类型为接口的注入点中自动装配实现 - How to autowire an implementation in an injection point whose type is an interface Spring Autowire - 接口和实现需要DAO类吗? - Spring Autowire - Interface and Implementation DAO Class needed? 弹簧单元测试:直接自动执行接口的实现? - Spring Unit Testing: Autowire the Implementation of an Interface directly? 如何通过类实现自动连接SecurityContextRepository - How to autowire SecurityContextRepository by class implementation 如何自动连接CrudRepository的实现实例 - How to autowire an instance of implementation of CrudRepository 如何自动连接具有多个实现的接口 - How to autowire an interface with multiple implementations Java Spring:自动装配基于同一属性值的接口实现 class - Java Spring: Autowire an implementation of an interface based on the value of a property in the same class Spring Autowire Bean具有多个接口实现,在方法中定义实现 - Spring Autowire Bean with multiple Interface Implementations, define Implementation in method 我们可以在 Spring 中自动装配一个没有任何实现的接口吗? - Could we autowire an interface without any implementation in Spring?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM