«Autowire» выходит из строя после развертывания пружинного модульного приложения на tomcat

1

Мне нужна помощь, так как я не могу найти решение самостоятельно, и google тоже не помогает. У меня есть модульное приложение весны, которое я могу запустить из командной строки с помощью SpringBoot без проблем. Я создал войну с помощью команды gradle war. Я установил Tomcat 8 на сервере с базой данных PostgreSQL и JRE 8. Я поместил войну в папку webapps и мои внешние файлы conf в папку conf. Все мои другие модули присутствуют в папке libs файла войны. Когда я запускаю Tomcat, я получаю следующую ошибку:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private eu.bato.anyoffice.serviceapi.service.PersonService eu.bato.anyoffice.frontend.config.PersonDetailsService.personService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [eu.bato.anyoffice.serviceapi.service.PersonService] 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)}

Вот часть моего основного файла conf:

@Configuration
@EnableAutoConfiguration
@ComponentScan(value = {"eu.bato.anyoffice"})
@EnableWebMvc
public class Application extends WebMvcConfigurerAdapter{

    @Autowired
    SchedulerService scheduler;

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

    @PostConstruct
    protected void startScheduler(){
        scheduler.start();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    }

    @Autowired
    private MessageSource messageSource;

Конфигурация безопасности, которая определяет компонент PersonDetailsService:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(personDetailsService()).passwordEncoder(new StandardPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(authenticationFilter(), LogoutFilter.class)
                .csrf().disable()
                .authorizeRequests()
                ......
                .permitAll();
    }

    @Bean
    PersonDetailsService personDetailsService() {
        return new PersonDetailsService();
    }

    @Bean
    Filter authenticationFilter() {
        BasicAuthenticationFilter basicAuthFilter = new BasicAuthenticationFilter(customAuthenticationManager(), new BasicAuthenticationEntryPoint());
        return basicAuthFilter;
    }

    @Bean
    ProviderManager customAuthenticationManager() {
        List<AuthenticationProvider> providers = new LinkedList<>();
        providers.add(daoAuthPovider());
        ProviderManager authenticationManager = new ProviderManager(providers);
        authenticationManager.setEraseCredentialsAfterAuthentication(true);
        return authenticationManager;
    }

    @Bean
    DaoAuthenticationProvider daoAuthPovider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(personDetailsService());
        provider.setPasswordEncoder(new StandardPasswordEncoder());
        //TODO: add salt
        return provider;
    }

Часть класса PersonDetailsService:

public class PersonDetailsService implements UserDetailsService {

    private static final Logger log = LoggerFactory.getLogger(PersonDetailsService.class);

    private static final StandardPasswordEncoder encoder = new StandardPasswordEncoder();

    @Autowired
    private PersonService personService;

    @Autowired
    private Environment environment;

    @PostConstruct
    protected void initialize() {
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("Authenticating: " + username);

Интерфейс PersonService находится в пакете eu.bato.anyoffice.serviceapi.service и его реализация находится в eu.bato.anyoffice.backend.service.impl и имеет теги @Service и @Transactional

Я был бы очень благодарен за любые намеки. Я могу предоставить любые дополнительные журналы и информацию.

  • 2
    в зависимости от того, как вы загружаете свой контекст, возможно, размещение @ComponentScan в SecurityConfig может решить вашу проблему
Теги:
spring
tomcat
autowired

1 ответ

1
Лучший ответ

Проблема в вашей конфигурации заключается в том, что PersonService загружается @ComponentScan объявленным в Servlet Context @ComponentScan.

Таким образом, PersonService недоступен в Application Context котором загружен ваш SecurityConfig.

Бобы в Servlet Context могут ссылаться на beans в Application Context, но не наоборот!

Таким образом, включение @ComponentScan в SecurityConfig позволяет этому компоненту быть повторно доступным.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню