简体   繁体   English

Spring配置文件默认行为

[英]Spring profile default behaviour

I have a spring profile "DEV" and thats the only profile I have and I do NOT want to create a "production" profile. 我有一个弹簧配置文件“DEV”,这是我唯一的配置文件,我不想创建一个“生产”配置文件。 So only when profile is "DEV" I would like a certain type of bean for spring security is initiated (which is an in memory guest user and a userdetails bean) 因此,只有当配置文件是“DEV”时,我才会启动某种类型的bean用于Spring安全性(这是一个内存来宾用户和一个userdetails bean)

But if no spring profile is provided in my tomcat startup, which is the case in production, I would like my app to continue what it is already doing(using ldap authenticatin provider). 但是如果我的tomcat启动中没有提供spring配置文件(生产中就是这种情况),我希望我的应用程序继续它已经在做的事情(使用ldap authenticatin提供程序)。

Is there a way to define a "default" bean behaviour without actually needing to provide a profile at start up? 有没有办法定义“默认”bean行为而不需要在启动时提供配置文件? Or you can look at my code below and suggest a different solution maybe. 或者您可以查看下面的代码,并提出一个不同的解决方案。

@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth, final AuthenticationProvider provider) throws Exception {

        auth
                .eraseCredentials(false)
                .authenticationProvider(provider)
                .authenticationProvider(jwtConfig.jwtAuthenticationProvider());
}


@Bean
public UserDetailsService userDetailsService() {
    final LdapUserDetailsService ldapUserDetailsService = new LdapUserDetailsService(ldapUserSearch(), ldapAuthoritiesPopulator());
    return new CompositeUserDetailsService(Arrays.asList(technicalUserDetailsService(), ldapUserDetailsService));
}

@Bean
@Profile("DEV")
public UserDetailsService devUserDetailsService() {
 useAnonymous = true;
        InMemoryUserDetailsManagerBuilder b = new InMemoryUserDetailsManagerBuilder()
                .withUser("user").password("password").authorities(ROLE_USER, ROLE_ADMIN).and();

        return new CompositeUserDetailsService(Arrays.asList(b.build(),
                technicalUserDetailsService()));

}
@Bean
public AuthenticationProvider ldapAuthenticationProvider() {
    final BindAuthenticator ba = new BindAuthenticator((BaseLdapPathContextSource) contextSource());
    ba.setUserSearch(ldapUserSearch());
    return new LdapAuthenticationProvider(ba, ldapAuthoritiesPopulator());
}

I think there is a misunderstanding of what @Profile does. 我认为对@Profile作用存在误解。 Beans marked with @Profile are only loaded when that profile is active, but all other beans (without a @Profile ) are still always loaded, regardless of the chosen profile. 标记为@Profile Bean仅在该配置文件处于活动状态时加载,但无论选择的配置文件如何,所有其他bean(没有@Profile )仍始终加载。

I see a few ways to solve this: 我看到几种解决方法:

1) Mark all those beans with a @Profile("dev") also with @Primary so Spring knows which one to pick when two beans of the same type are loaded (since you donot want to use a production profile). 1)使用@Primary标记所有那些带有@Profile("dev") @Primary因此Spring知道在加载两个相同类型的bean时要选择哪一个(因为你不想使用生产配置文件)。

2) Mark the beans that should not be loaded when profile dev is active with @Profile("!dev") -- only applicable for Spring 3.2 and higher (see https://github.com/spring-projects/spring-framework/commit/bcd44f3798ed06c0704d2a3564b8a9735e747e87 ). 2)记住,当轮廓开发与活跃, 应该装豆@Profile("!dev") -仅适用于春季3.2和更高版本(见https://github.com/spring-projects/spring-framework / commit / bcd44f3798ed06c0704d2a3564b8a9735e747e87 )。

Or... 要么...

3) Use a production profile and simply activate it in for example the web.xml file (something which you probably don't use locally). 3)使用生产配置文件并在例如web.xml文件(您可能不在本地使用的东西)中激活它。

Simply create multiple @Configuration classes and mark the entire class with a profile (it also helps to keep related stuff together). 只需创建多个@Configuration类并使用配置文件标记整个类(它还有助于将相关内容保存在一起)。 A typical example is for the database. 典型的例子是数据库。 Create one configuration class for the production database (something with JNDI and Oracle) and one for local development and testing (HSQLDB). 为生产数据库(使用JNDI和Oracle)创建一个配置类,为本地开发和测试(HSQLDB)创建一个配置类。

You mark the JNDI Configuration class with @Profile("production") and the other with @Profile("dev") -- no need to mark individual beans, just split them logically amongst two different @Configuration classes. 使用@Profile("production")标记JNDI Configuration类,使用@Profile("dev")标记另一个 - 不需要标记单个bean,只需在逻辑上将它们分成两个不同的@Configuration类。

This worked really well for us, also when combined with integration testing. 这对我们来说非常有效,当与集成测试结合使用时也是如此。

I would override the bean definition in this way: 我会以这种方式覆盖bean定义:

@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth, final AuthenticationProvider provider) throws Exception {

        auth
                .eraseCredentials(false)
                .authenticationProvider(provider)
                .authenticationProvider(jwtConfig.jwtAuthenticationProvider());
}


@Bean("myUserDetailService")
public UserDetailsService userDetailsService() {
    final LdapUserDetailsService ldapUserDetailsService = new LdapUserDetailsService(ldapUserSearch(), ldapAuthoritiesPopulator());
    return new CompositeUserDetailsService(Arrays.asList(technicalUserDetailsService(), ldapUserDetailsService));
}

@Bean("myUserDetailService")
@Profile("DEV")
public UserDetailsService devUserDetailsService() {
 useAnonymous = true;
        InMemoryUserDetailsManagerBuilder b = new InMemoryUserDetailsManagerBuilder()
                .withUser("guest").password("guest").authorities(ROLE_USER, ROLE_ADMIN).and();

        return new CompositeUserDetailsService(Arrays.asList(b.build(),
                technicalUserDetailsService()));

}
@Bean("myAuthProvider")
public AuthenticationProvider ldapAuthenticationProvider() {
    final BindAuthenticator ba = new BindAuthenticator((BaseLdapPathContextSource) contextSource());
    ba.setUserSearch(ldapUserSearch());
    return new LdapAuthenticationProvider(ba, ldapAuthoritiesPopulator());
}

@Bean("myAuthProvider")
@Profile("DEV")
public AuthenticationProvider devAuthenticationProvider() {

   //find a way to return userdetails here

}

In this way when the "DEV" profile is started the beans defined in that profile should override the default beans 这样,当启动“DEV”配置文件时,该配置文件中定义的bean应覆盖默认bean

Sure when you autowire beans you should use the @Qualifier annotation 当你自动装豆时,你应该使用@Qualifier注释

I hope it's useful 我希望它有用

Angelo 安杰洛

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM