我在堆栈溢出中遇到了一个有趣的问题。 Brett Ryan有问题,Spring Security配置被初始化了两次。 当我查看他的代码时,我发现了问题所在。 让我展示显示代码。
他有相当标准的Spring应用程序(不使用Spring Boot)。 使用基于Spring的AbstractAnnotationConfigDispatcherServletInitializer
更现代的Java servlet配置。
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[]{"/"};
}
}
如您所见,有两个配置类:
-
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 {
@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 {
}
注意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的组件扫描排除的特殊软件包。
翻译自: https://www.javacodegeeks.com/2014/12/avoid-unwanted-component-scanning-of-spring-configuration.html