Невозможно создать компонент с помощью @Autowired - PullRequest
1 голос
/ 30 июня 2019

Я настраиваю свой проект Spring для использования Spring Security.

Я хотел бы использовать аутентификацию JDBC и подключиться к базе данных MySQL. У меня проблема с созданием bean-компонента с @Autowired.

Я построил свой весенний проект с 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) (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");
  }
}
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();
  }
}
DataSourceConfig
@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 Ответ

1 голос
/ 30 июня 2019

Ваш проект не может найти datasourceBean,

измените

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

, чтобы включить пакет класса DataSourceConfig

, например DataSourceConfig находится впакет my.test.package.DataSourceConfig

по крайней мере ComponentScan должен быть

@ComponentScan(`my.test.package")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...