[英]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.