gpt4 book ai didi

java - 使用 xml 和注解配置两次加载 Spring 上下文

转载 作者:行者123 更新时间:2023-11-29 03:28:08 25 4
gpt4 key购买 nike

我在 Tomcat 7.0.34、Spring 3.2.3、Spring Security 3.2.0.RC1 和 Spring Social 1.1 上有一个 Web 应用程序。

出于某种原因,Spring 上下文被加载了两次。第二次加载在第一次加载完成后立即发生。下面的日志显示了上下文加载器加载根 WebApplicationContext。一切都在正常进行,所有 RequstMappingHandlers 都在正确注册。然后立即再次刷新上下文。

我已经阅读了关于确保您不会同时加载配置作为上下文加载器和 DispatcherServlet 的一部分的几个解决方案,并且测试了这个的各种组合,但似乎没有修复它而且我也变得代码盲了。

我对此的所有测试都将我推向了容器和 Spring 组件的仅注解配置,但配置类几乎是从 github 上的 Spring Social 示例复制和粘贴的。虽然我在下面包含了 SocialConfig.java 的详细信息,但这个问题在我实现 Spring Social 之前就已经发生了,但如果不修复它我就无法继续。

此外,问题还存在于混合 xml(web.xml、security-app-context.xml)和注释配置中。

我正在实现 WebApplicationInitializer 而不是 web.xml

public class WebClientInitialiser implements WebApplicationInitializer {

public void onStartup(ServletContext container) throws ServletException {

// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();

// Manage the lifecycle of the root application context
appContext.setConfigLocation("com.mycompany.webclient.config");
appContext.setServletContext(container);

container.addListener(new ContextLoaderListener(appContext));
container.addListener(new MyCompanyContextListener());

container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");

// Register and map the dispatcher servlet
Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(appContext));
dispatcher.addMapping("/");
dispatcher.setLoadOnStartup(1);
}

}

我的主配置.java

/**
* Main configuration class for the application.
* Turns on @Component scanning, loads externalized application properties
* and imports legacy security configuration
*/
@Configuration
@ComponentScan(basePackages = "com.mycompany.webclient", excludeFilters = { @Filter(Configuration.class) })
@PropertySource("classpath:wc.properties")
@ImportResource("/WEB-INF/spring/appServlet/security-app-context.xml")
public class MainConfig {


@Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}

}

我的WebMvcConfig.java

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}

@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/WEB-INF/messages/messages");
return messageSource;
}

@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}

我的 SocialConfig.java

@Configuration
@EnableSocial
public class SocialConfig implements SocialConfigurer {

private SocialUserDAO socialUserDao;
//
// SocialConfigurer implementation methods
//

@Override
public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
String clientId="XXXXXX";
String clientSecret="XXXXX";
cfConfig.addConnectionFactory(new FacebookConnectionFactory(clientId, clientSecret));
}

@Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
@Override
public String getUserId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
}
return authentication.getName();
}
};
}

@Override
public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new HibernateUsersConnectionRepository(socialUserDao, connectionFactoryLocator, Encryptors.noOpText());
}

//
// API Binding Beans
//

@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Facebook facebook(ConnectionRepository repository) {
Connection<Facebook> connection = repository.findPrimaryConnection(Facebook.class);
return connection != null ? connection.getApi() : null;
}

@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Twitter twitter(ConnectionRepository repository) {
Connection<Twitter> connection = repository.findPrimaryConnection(Twitter.class);
return connection != null ? connection.getApi() : null;
}

@Bean
@Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public LinkedIn linkedin(ConnectionRepository repository) {
Connection<LinkedIn> connection = repository.findPrimaryConnection(LinkedIn.class);
return connection != null ? connection.getApi() : null;
}

//
// Web Controller and Filter Beans
//
@Bean
public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {
ConnectController connectController = new ConnectController(connectionFactoryLocator, connectionRepository);
connectController.addInterceptor(new PostToWallAfterConnectInterceptor());
connectController.addInterceptor(new TweetAfterConnectInterceptor());
return connectController;
}

@Bean
public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SimpleSignInAdapter(new HttpSessionRequestCache()));
}

@Bean
public DisconnectController disconnectController(UsersConnectionRepository usersConnectionRepository, Environment env) {
return new DisconnectController(usersConnectionRepository, env.getProperty("facebook.clientSecret"));
}

@Bean
public ReconnectFilter apiExceptionHandler(UsersConnectionRepository usersConnectionRepository, UserIdSource userIdSource) {
return new ReconnectFilter(usersConnectionRepository, userIdSource);
}

}

非常感谢任何帮助、评论和指点。

此日志输出在每次上下文刷新开始时重复两次:

org.springframework.web.context.ContextLoader- Root WebApplicationContext: initialization started
org.springframework.web.context.support.AnnotationConfigWebApplicationContext- Refreshing Root WebApplicationContext: startup date [Mon Nov 25 22:43:39 GMT 2013]; root of context hierarchy
org.springframework.context.annotation.ClassPathBeanDefinitionScanner- JSR-330 'javax.inject.Named' annotation found and supported for component scanning
org.springframework.web.context.support.AnnotationConfigWebApplicationContext- Registering annotated classes: [class com.mycompany.webclient.config.WebMvcConfig,class com.mycompany.webclient.config.SocialConfig]

最佳答案

您将相同的上下文传递给 ContextLoaderListenerDispatcherServlet,因此这将触发两次加载配置。

您应该有 2 个单独的 AnnotationConfigWebApplicationContext 实例,一个用于 ContextLoaderListener 加载所有通用 bean(服务等),另一个用于 DispatcherServlet加载网络相关的东西。

public class WebClientInitialiser implements WebApplicationInitializer {

public void onStartup(ServletContext container) throws ServletException {

// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(MainConfig.class);
// Manage the lifecycle of the root application context

container.addListener(new ContextLoaderListener(rootContext));
container.addListener(new MyCompanyContextListener());

container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");

AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(WebMvcConfig.class, SocialConfig.class);

// Register and map the dispatcher servlet
Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.addMapping("/");
dispatcher.setLoadOnStartup(1);
}

}

是这样的。此外,您无需设置 contextConfigLocation,只需注册 @Configuration 注释类即可。此外设置 ServletContext 已经由 Spring 完成,因此不需要这样做。

请注意您的配置,默认情况下启用 PropertySourcesPlaceHolderConfigurer,因此无需在 MainConfig 类中再次注册。

另一件需要考虑的事情是,现在您的应用程序可能会失败(即您的 @Controllers 不再工作)。这是因为所有内容都在根应用程序上下文中,而 @Controllers 应该由 DispatcherServlet 加载。要解决此问题,您需要在 MainConfig 中排除 @Controller 扫描并在 WebMvcConfig 类上启用 @Controller 扫描.

关于java - 使用 xml 和注解配置两次加载 Spring 上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19896421/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com