我在堆栈溢出中遇到了一个有趣的问题。 Brett Ryan有问题,Spring Security配置被初始化了两次。 当我查看他的代码时,我发现了问题所在。 让我展示显示代码。
他有相当标准的Spring应用程序(不使用Spring Boot)。 使用基于Spring的AbstractAnnotationConfigDispatcherServletInitializer
更现代的Java servlet配置。
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class AppInitializer extendsAbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{SecurityConfig.class};}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{WebConfig.class};}@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}}
如您所见,有两个配置类:
-
SecurityConfig
–保存Spring Security配置 -
WebConfig
– Spring的主要IoC容器配置
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 {@Autowiredpublic 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 {}
注意WebConfig
的组件扫描。 这是扫描软件包,所有三个类都位于该软件包中。 在servlet容器上运行此命令时,将文本“ Spring Security init…”写入控制台两次。 这意味着SecurityConfig
配置被加载两次。 它已加载:
- 在方法
AppInitializer.getRootConfigClasses()
的Servlet容器初始化期间 - 通过类
WebConfig
组件扫描
为什么? 我在Spring的文档中找到了这种解释 :
请记住,
@Configuration
类使用@Component
进行元注释 ,因此它们是组件扫描的候选对象!
因此,这是Spring的功能,因此我们要避免Servlet配置使用的Spring @Configuration
组件扫描。 Brett Ryan独立地发现了这个问题,并在提到的Stack Overflow问题中展示了他的解决方案:
@ComponentScan(basePackages = "com.acme.app",excludeFilters = {@Filter(type = ASSIGNABLE_TYPE,value = {WebConfig.class,SecurityConfig.class})})
我不喜欢这种解决方案。 注释对我来说太冗长了。 另外,一些开发人员可以创建新的@Configuration
类,而忘记将其包含在此过滤器中。 我宁愿指定将被Spring的组件扫描排除的特殊软件包。
- 我在Github上创建了示例项目,以便您可以使用它。
翻译自: https://www.javacodegeeks.com/2014/12/avoid-unwanted-component-scanning-of-spring-configuration.html