DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Building a CRUD Application With Spring and SimpleJdbcMapper
  • How to Marry MDC With Spring Integration
  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux

Trending

  • Evaluating SOC Effectiveness Using Detection Coverage and Response Metrics
  • LLM Agents and Getting Started with Them
  • The Hidden Cost of Overprivileged Tokens: Designing Messaging Platforms That Assume Compromise
  • S3 Vectors: How to Build a RAG Without a Vector Database
  1. DZone
  2. Coding
  3. Frameworks
  4. Avoid Unwanted Component Scanning of Spring Configuration

Avoid Unwanted Component Scanning of Spring Configuration

By 
Lubos Krnac user avatar
Lubos Krnac
·
Dec. 04, 14 · Interview
Likes (1)
Comment
Save
Tweet
Share
47.9K Views

Join the DZone community and get the full member experience.

Join For Free

I came through interesting problem on Stack Overflow. Brett Ryan had problem that Spring Security configuration was initialized twice. When I was looking into his code I spot the problem. Let me show show the code.

He has pretty standard Spring application (not using Spring Boot). Uses more modern Java servlet Configuration based on Spring’s AbstractAnnotationConfigDispatcherServletInitializer.

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
 
public class AppInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {
 
 
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SecurityConfig.class};
    }
 
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }
 
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
 
}

As you can see, there are two configuration classes:

  • SecurityConfig – holds Spring Security configuration
  • WebConfig – main Spring’s IoC container configuration
package net.lkrnac.blog.dontscanconfigurations;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
 
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("Spring Security init...");
        auth
                .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
 
}
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "net.lkrnac.blog.dontscanconfigurations")
public class WebConfig extends WebMvcConfigurerAdapter {
 
}

Pay attention to the component scanning in WebConfig. It is scanning package where all three classes are located. When you run this on servlet container, text “Spring Security init…” is written to console twice. It mean mean SecurityConfig configuration is loaded twice. It was loaded

  1. During creation of root context in method AppInitializer.getRootConfigClasses()
  2. By component scan in class WebConfig. This instance is created as part of servlet context creation in method AppInitializer.getServletConfigClasses().

Why? I found this explanation in Spring’s documentation:

Remember that @Configuration classes are meta-annotated with @Component, so they are candidates for component-scanning!

So this is feature of Spring and therefore we want to avoid component scanning of Spring @Configuration used by Servlet configuration. Brett Ryan independently found this problem and showed his solution in mentioned Stack Overflow question:

@ComponentScan(basePackages = "com.acme.app",
               excludeFilters = {
                   @Filter(type = ASSIGNABLE_TYPE,
                           value = {
                               WebConfig.class,
                               SecurityConfig.class
                           })
               })

I don’t like this solution. Annotation is too verbose for me. Also some developer can create new @Configuration class and forget to include it into this filter. I would rather specify special package that would be excluded from Spring’s component scanning.

Even better solution for this problem would be for me not to define separate contexts and rather use only servlet context as described in Spring Reference Documentation. Far most optimal solution is using Spring Boot with embedded servlet container, where you don’t need to define AbstractAnnotationConfigDispatcherServletInitializer at all.

I created sample project on Github so that you can play with it.



Spring Framework

Published at DZone with permission of Lubos Krnac. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Building a CRUD Application With Spring and SimpleJdbcMapper
  • How to Marry MDC With Spring Integration
  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook