无法使用@Autowired创建bean

时间:2019-06-30 09:15:28

标签: java mysql spring gradle spring-security

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

我想使用JDBC身份验证并连接到MySQL数据库。 我无法使用@Autowired创建bean。

我用Gradle建立了我的春季项目。当我启动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) (这三个类在软件包“(我的顶级软件包名称).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");
  }
}
WebSecurityConfig
@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)
build.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对象,并查看登录页面。

1 个答案:

答案 0 :(得分:1)

您的项目找不到datasourceBean,

更改

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

以包含DataSourceConfig类包

例如DataSourceConfig位于软件包my.test.package.DataSourceConfig

至少ComponentScan应该是

@ComponentScan(`my.test.package")