【问题标题】:Cannot create bean with @Autowired无法使用 @Autowired 创建 bean
【发布时间】:2019-11-11 09:40:42
【问题描述】:

我正在设置我的 spring 项目以使用 Spring Security。

我想使用 JDBC 身份验证并连接到 MySQL 数据库。 我在使用 @Autowired 创建 bean 时遇到问题。

我使用 Gradle 构建了我的 spring 项目。当我启动 tomcat 时,我看到如下错误消息。

错误信息

ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webSecurityConfig': Unsatisfied dependency expressed through field 'dataSource'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.apache.commons.dbcp2.BasicDataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:400)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:291)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4680)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5150)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:928)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:634)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.apache.commons.dbcp2.BasicDataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1654)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1213)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
    ... 45 more

源代码

我创建了 3 个 Java 配置类,如下所示。

  • WebMvcConfig.class(实现 WebMvcConfigurer)
  • WebSecurityConfig.class(扩展 WebSecurityConfigurerAdapter)
  • DataSourceConfig.class(包括 @Bean 方法返回 BasicDataSource) (这3个类都在包“(我的顶级包名).config中)
WebMvcConfig
@Configuration
@EnableWebMvc
@Import(ThymeleafConfig.class)
@ComponentScan("(my top level package name).controller")
public class WebMvcConfig implements WebMvcConfigurer {

  @Bean
  public RequestMappingHandlerMapping requestMappingHandlerMapping() {
    return new RequestMappingHandlerMapping();
  }

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("static/**").addResourceLocations("classpath:/static/");
  }

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/login").setViewName("general/login");
  }
}
网络安全配置
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(10);
  }

  @Bean
  public RequestMatcher logoutRequestMatcher() {
    return new AntPathRequestMatcher("/logout");
  }

  @Autowired
  BasicDataSource dataSource;


  @Autowired
  public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.jdbcAuthentication().dataSource(dataSource)
        .authoritiesByUsernameQuery(
            "select mail_address as username, 'USER' as authority from personnel "
                + " where personnel_id = ?")
        .usersByUsernameQuery(
            "select mail_address as username, password, true as enabled from personnel "
                + " where personnel_id = ?")
        .passwordEncoder(passwordEncoder());
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/login", "/logout").permitAll().anyRequest()
        .authenticated();
    http.formLogin();
    http.logout().logoutRequestMatcher(logoutRequestMatcher()).invalidateHttpSession(true).and()
        .csrf();
  }
}
数据源配置
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
  @Bean
  public BasicDataSource dataSource() {
    BasicDataSource basicDataSource = new BasicDataSource();
    basicDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    basicDataSource.setUrl(
        "jdbc:mysql://localhost:3306/(my database name)?characterEncoding=UTF-8&serverTimezone=JST&useSSL=false");
    basicDataSource.setUsername("(username)");
    basicDataSource.setPassword("(password)");
    return basicDataSource;
  }
}
“人事”表
mysql> SHOW COLUMNS FROM personnel;
+-----------------------+-------------------------------+------+-----+---------+----------------+
| Field                 | Type                          | Null | Key | Default | Extra          |
+-----------------------+-------------------------------+------+-----+---------+----------------+
| personnel_id          | smallint(4) unsigned zerofill | NO   | PRI | NULL    | auto_increment |
| insrance_num          | varchar(15)                   | YES  |     | NULL    |                |
| first_name            | varchar(20)                   | NO   |     | NULL    |                |
| last_name             | varchar(20)                   | NO   |     | NULL    |                |
| first_name_kana       | varchar(20)                   | NO   |     | NULL    |                |
| last_name_kana        | varchar(20)                   | NO   |     | NULL    |                |
| gender                | char(1)                       | NO   |     | NULL    |                |
| birthday              | date                          | NO   |     | NULL    |                |
| postal_code           | char(8)                       | NO   |     | NULL    |                |
| address               | varchar(100)                  | NO   |     | NULL    |                |
| entering_company_date | date                          | NO   |     | NULL    |                |
| mail_address          | varchar(254)                  | NO   |     | NULL    |                |
| contract_type_id      | smallint(3) unsigned zerofill | YES  | MUL | NULL    |                |
| retiremented_flg      | bit(1)                        | NO   |     | b'0'    |                |
| retirement_date       | date                          | YES  |     | NULL    |                |
| next_holiday          | date                          | YES  |     | NULL    |                |
| password              | varchar(100)                  | NO   |     | NULL    |                |
+-----------------------+-------------------------------+------+-----+---------+----------------+
17 rows in set (0.08 sec)
构建.gradle
plugins {
    id 'java'
    id 'eclipse'
    id 'eclipse-wtp'
    id 'war'
    id "io.freefair.lombok" version "3.7.5"
}

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}
repositories {
    jcenter()
}

dependencies {
    // spring framework
    implementation "org.springframework:spring-context:${springVersion}"
    implementation "org.springframework:spring-webmvc:${springVersion}"
    implementation "org.springframework:spring-jdbc:${springVersion}"
    implementation "org.springframework:spring-tx:${springVersion}"
    implementation "org.springframework.security:spring-security-web:${springVersion}"
    implementation "org.springframework.security:spring-security-config:${springVersion}"
    
    //db
    implementation "org.mybatis:mybatis:3.5.1"
    implementation "org.mybatis:mybatis-spring:2.0.1"
    implementation "mysql:mysql-connector-java:${jdbcVersion}"
    implementation "org.apache.commons:commons-dbcp2:2.6.0"
    
    
    //thymeleaf
    implementation "org.thymeleaf:thymeleaf-spring5:${thymeleafSpringVersion}"
    implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.0.4.RELEASE"
    
    //Logger
    implementation "org.slf4j:slf4j-api:${slf4jVersion}"
    implementation "org.slf4j:slf4j-log4j12:${slf4jVersion}"
    
    //others
    implementation "javax.servlet:jstl:${jstlVersion}"
    implementation "javax.validation:validation-api:${validationApiVersion}"
    compileOnly "javax.servlet:javax.servlet-api:${servletApiVersion}"
}

group = 'xxx'
version = '1.0.0-BUILD-SNAPSHOT'
description = 'xxx'
sourceCompatibility = '1.11'

我的预期

我希望创建一个 BasicDataSource 对象并查看登录页面。

【问题讨论】:

  • 感谢您的评论。我已经添加了“build.gradle”(gradle的构建配置文件)的内容。

标签: java mysql spring gradle spring-security


【解决方案1】:

你的项目找不到 datasourceBean ,

改变

@ComponentScan("(my top level package name).controller")

为了包含DataSourceConfig类包

例如 DataSourceConfig 在包中 my.test.package.DataSourceConfig

至少ComponentScan 应该是

@ComponentScan(`my.test.package")

【讨论】:

  • 我如你所说更改了 WebMvcConfig 并在 WebSecurityConfig 中添加了“@ComponentScan("(我的顶级包名)")”。我已经成功启动了tomcat并看到了登录页面!感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-04
  • 2016-02-20
  • 1970-01-01
  • 2021-08-21
  • 2021-07-12
  • 1970-01-01
  • 2021-03-03
相关资源
最近更新 更多