SpringBoot应用程序需要一个带有@Primary注释的bean来启动
我在Spring Boot应用程序启动时看到以下消息:SpringBoot应用程序需要一个带有@Primary注释的bean来启动,spring,spring-boot,Spring,Spring Boot,我在Spring Boot应用程序启动时看到以下消息: > *************************** APPLICATION FAILED TO START > *************************** > > Description: > > Field oauthProps in com.example.authservice.AuthorizationServerConfig > required a single
> *************************** APPLICATION FAILED TO START
> ***************************
>
> Description:
>
> Field oauthProps in com.example.authservice.AuthorizationServerConfig
> required a single bean, but 2 were found:
> - OAuthProperties: defined in file [/Users/simeonleyzerzon/abc/spring-security/spring-security-5-oauth-client/auth-service/target/classes/com/example/authservice/config/OAuthProperties.class]
> - kai-com.example.authservice.config.OAuthProperties: defined in null
>
>
> Action:
>
> Consider marking one of the beans as @Primary, updating the consumer
> to accept multiple beans, or using @Qualifier to identify the bean
> that should be consumed
我想知道是什么导致了该bean的重复,以及如何在不需要使用@Primary
注释的情况下删除它?不确定上面的kai com包(?)来自何处
下面是一个问题:
package com.example.authservice.config;
//@Primary
@Component
@ConfigurationProperties(prefix="kai")
@Setter @Getter
public class OAuthProperties {
private String[] redirectUris;
private String clientId;
private String clientSecret;
private final Token token = new Token();
@Setter @Getter
public static class Token{
private String value;
private String type="";
}
}
以及app/config等:
package com.example.authservice;
import ...
@SpringBootApplication
public class AuthServiceApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServiceApplication.class, args);
}
}
@Controller
class MainController {
@GetMapping("/")
String index() {
return "index";
}
}
@RestController
class ProfileRestController {
@GetMapping("/resources/userinfo")
Map<String, String> profile(Principal principal) {
return Collections.singletonMap("name", principal.getName());
}
}
@Configuration
@EnableResourceServer
class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/resources/**")
.authorizeRequests()
.mvcMatchers("/resources/userinfo").access("#oauth2.hasScope('profile')");
}
}
@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(OAuthProperties.class)
class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired private OAuthProperties oauthProps;
private final AuthenticationManager authenticationManager;
AuthorizationServerConfig(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(oauthProps.getClientId())
.secret(oauthProps.getClientSecret())
.authorizedGrantTypes("authorization_code")
.scopes("profile")
.redirectUris(oauthProps.getRedirectUris());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(this.authenticationManager);
if (oauthProps.getToken().getType().equals("jwt")) {
endpoints.tokenStore(this.tokenStore()).accessTokenConverter(jwtAccessTokenConverter());
}else {
endpoints.tokenEnhancer(eapiTokenEnhancer());
}
}
TokenEnhancer eapiTokenEnhancer() {
return new TokenEnhancer() {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
result.setValue(oauthProps.getToken().getValue());
return result;
}
};
}
@Bean
JwtAccessTokenConverter jwtAccessTokenConverter() {
KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource(".keystore-oauth2-demo"), //keystore
"admin1234".toCharArray()); //storepass
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setKeyPair(factory.getKeyPair("oauth2-demo-key")); //alias
return jwtAccessTokenConverter;
}
@Bean
TokenStore tokenStore() {
return new JwtTokenStore(this.jwtAccessTokenConverter());
}
}
@Service
class SimpleUserDetailsService implements UserDetailsService {
private final Map<String, UserDetails> users = new ConcurrentHashMap<>();
SimpleUserDetailsService() {
Arrays.asList("josh", "rob", "joe")
.forEach(username -> this.users.putIfAbsent(
username, new User(username, "pw", true, true, true, true, AuthorityUtils.createAuthorityList("USER","ACTUATOR"))));
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return this.users.get(username);
}
}
@Configuration
@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
}
package com.example.authservice;
导入。。。
@SpringBoot应用程序
公共类AuthServiceApplication{
公共静态void main(字符串[]args){
run(AuthServiceApplication.class,args);
}
}
@控制器
类主控制器{
@GetMapping(“/”)
字符串索引(){
返回“索引”;
}
}
@RestController
类ProfileRestController{
@GetMapping(“/resources/userinfo”)
地图简介(校长){
返回Collections.singletonMap(“name”,principal.getName());
}
}
@配置
@EnableResourceServer
类ResourceServerConfig扩展了ResourceServerConfigurerAdapter{
@凌驾
public void configure(HttpSecurity http)引发异常{
http
.antMatcher(“/resources/**”)
.授权请求()
.mvcMatchers(“/resources/userinfo”).access(“#oauth2.hasScope('profile')”);
}
}
@配置
@EnableAuthorizationServer
@EnableConfigurationProperties(OAuthProperties.class)
类AuthorizationServerConfig扩展AuthorizationServerConfigurerAdapter{
@自动连线专用OAuthProperties oauthProps;
私人最终身份验证经理AuthenticationManager;
AuthorizationServerConfig(AuthenticationManager AuthenticationManager){
this.authenticationManager=authenticationManager;
}
@凌驾
公共无效配置(ClientDetailsServiceConfigurer客户端)引发异常{
客户
.inMemory()
.withClient(oauthProps.getClientId())
.secret(oauthProps.getClientSecret())
.authorizedGrantTypes(“授权代码”)
.范围(“概要文件”)
.redirectUris(oauthProps.getRedirectUris());
}
@凌驾
public void configure(AuthorizationServerEndpointsConfigurer端点)引发异常{
endpoints.authenticationManager(this.authenticationManager);
if(oauthProps.getToken().getType().equals(“jwt”)){
endpoints.tokenStore(this.tokenStore()).accessTokenConverter(jwtAccessTokenConverter());
}否则{
标记增强器(eapiTokenEnhancer());
}
}
令牌增强子eapiTokenEnhancer(){
返回新的令牌增强器(){
@凌驾
公共OAuth2AccessToken增强(OAuth2AccessToken accessToken,OAuth2Authentication身份验证){
DefaultOAuth2AccessToken结果=新的DefaultOAuth2AccessToken(accessToken);
setValue(oauthProps.getToken().getValue());
返回结果;
}
};
}
@豆子
JwtAccessTokenConverter JwtAccessTokenConverter(){
KeyStoreKeyFactory=newkeystorekeyFactory(newclasspathResource(“.keystore-oauth2-demo”),//keystore
“admin1234.toCharArray());//storepass
JwtAccessTokenConverter JwtAccessTokenConverter=新的JwtAccessTokenConverter();
jwtAccessTokenConverter.setKeyPair(工厂.getKeyPair(“oauth2演示密钥”);//别名
返回JWT转换器;
}
@豆子
TokenStore TokenStore(){
返回新的JwtTokenStore(this.jwtAccessTokenConverter());
}
}
@服务
类SimpleUserDetailsService实现UserDetailsService{
私有最终映射用户=新ConcurrentHashMap();
SimpleUserDetailsService(){
数组。asList(“josh”、“rob”、“joe”)
.forEach(用户名->this.users.putIfAbsent(
用户名,新用户(用户名,“pw”,true,true,true,AuthorityUtils.createAuthorityList(“用户”,“执行器”));
}
@凌驾
public UserDetails loadUserByUsername(字符串用户名)引发UsernameNotFoundException{
返回此.users.get(用户名);
}
}
@配置
@启用Web安全性
类SecurityConfig扩展了WebSecurity配置适配器{
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http
.授权请求()
.anyRequest().authenticated()
.及()
.formLogin();
}
}
Eclipse似乎也只知道bean的一个实例:
以下更改(删除@EnableConfigurationProperties
)似乎有助于缓解对@Primary注释的需求:
@Configuration
@EnableAuthorizationServer
//@EnableConfigurationProperties(OAuthProperties.class)
class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired private OAuthProperties oauthProps;
也许有人可以通过注释来描述二次bean创建的内部Spring机制(及其名称空间/包分配),该注释似乎会导致与@Autowired
one的冲突,或者向我指出此行为的适当文档 以下更改(删除@EnableConfigurationProperties
)似乎有助于缓解对@Primary注释的需求:
@Configuration
@EnableAuthorizationServer
//@EnableConfigurationProperties(OAuthProperties.class)
class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired private OAuthProperties oauthProps;
也许有人可以通过注释来描述二次bean创建的内部Spring机制(及其名称空间/包分配),该注释似乎会导致与
@Autowired
one的冲突,或者向我指出此行为的适当文档 将@EnableConfigurationProperties
与@ConfigurationProperties
一起使用时,您将得到一个名为-
的bean,即kai com.example.authservice.config.OAuthProperties
。(另见)
当@ConfigurationProperties
bean以这种方式注册时,该bean有一个常规名称:-
,