본문 바로가기

Language & Framework/삽질기록

삽질 기록 (4) 같은 타입의 Bean이 두 개 이상 존재할 때

 

 

스프링 시큐리티를 연습하다가 이런 에러를 만났다.

 

 

 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 3 of constructor in study.security.securitypack.configs.SecurityConfig
required a single bean, but 3 were found:
	- ajaxAuthenticationSuccessHandler: 
    defined in file [/Desktop/java/security/build/classes/java/main/study/security/securitypack/handler/AjaxAuthenticationSuccessHandler.class]
	- customAuthenticationSuccessHandler: 
    defined in file [/Desktop/java/security/build/classes/java/main/study/security/securitypack/handler/CustomAuthenticationSuccessHandler.class]
	- authenticationSuccessHandler: 
    defined by method 'authenticationSuccessHandler' in class path resource [study/security/securitypack/configs/AjaxSecurityConfig.class]


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

 

 

끄덕끄덕.. 

우리의 친절한 스프링 부트가 뭐가 문제와 해결책까지 모두 알려주고 있다.

Html Form 전송 방식과 Ajax 통신을 통한 비동기 방식으로 각각 핸들러를 구현했더니 같은 타입의 빈이 2개라서 어떤 걸 붙여줘야할지 모르니 @Primary나 @Qulifier를 붙이라고 한다.

 

지금까지 같은 타입의 빈을 두 개 사용해볼 일이 없던터라 저게 뭔지 기억 안 난다 ㅎㅎ..

Qulifier는 사용해본 기억이라도 있는데 Primary는 정말 처음 보는 것 같다..

 

 

 

 

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Qualifier.html

 

Qualifier (Spring Framework 5.3.22 API)

 

docs.spring.io

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Primary.html

 

Primary (Spring Framework 5.3.22 API)

Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value. This annotation is semantically equiv

docs.spring.io

 

 

 

특정 빈을 매칭해주는 어노테이션 = @Qulifier

특정 빈을 매칭해놓지 않았으나 같은 타입의 빈이 여러개 있을 때 기본값으로 쓰고 싶은 경우 = @Primary

 

설명을 읽어보니 배웠던 기억이 나는구만..

나는 혹시 몰라서 미래의 귀찮음을 방지하기 위해 모두 Qulifier로 만들기로 했다.

 

 

 

 

 

그런데 이거 쓰려면 @RequiredArgsConstructor를 못 쓴다.....

어쩔 수 없지..

 

사용법은 쉽다

 

 

 

 

 

우선 해당 클래스 위에 @Qulifier("님이 원하는 이름") 붙여주고

 

 

 

 

deprecated 불 - 편

 

 

생성자에서도 그대로 붙여주면 된다.

 

참고로 클래스 위에는 안 붙여줘도 된다. 예를 들어 AjaxAuthenticationSuccessHandler의 경우 별도의 지정이 없으면 SpringBeanContainer에 ajaxAuthenticationSuccessHandler라는 이름으로 등록되는데(제일 앞 글자만 소문자로 바꾸면 됨)

Qulifier는 만약 매칭되는 빈이 없으면 그 다음에는 빈 이름으로 탐색하기 때문에, 파라미터에만 @Qulifier("ajaxAuthenticationSuccessHandler")라고 붙여줘도 되지만..

 

기왕 귀찮은거 깔끔하고 알아보기 쉽게 양쪽 모두 지정해줬다

 

끝.