NoSuch Bean 정의란?예외 사항 및 수정 방법은 무엇입니까?
에 대해 다음과 같이 설명해주시기 바랍니다.NoSuchBeanDefinitionException
스프링에서의 예외:
- 그것은 무엇을 뜻하나요?
- 어떤 조건으로 던지나요?
- 어떻게 하면 막을 수 있을까요?
이 게시물은 발생에 대한 종합적인 Q&A를 목적으로 작성되었습니다.NoSuchBeanDefinitionException
스프링을 사용하는 응용 프로그램에서.
설명의 자바독은
a일 때 예외가 발생했습니다.
BeanFactory
정의를 찾을 수 없는 빈 인스턴스를 요청합니다.이는 존재하지 않는 빈, 고유하지 않은 빈 또는 관련된 빈 정의가 없는 수동 등록 싱글톤 인스턴스를 가리킬 수 있습니다.
A는 기본적으로 Spring의 Inversion of Control 컨테이너를 나타내는 추상화입니다.그것은 당신의 애플리케이션에 내외부적으로 콩을 노출시킵니다.이 콩들을 찾거나 회수할 수 없을 때, 그것은 던집니다.NoSuchBeanDefinitionException
.
아래는 왜 a인지에 대한 간단한 이유입니다.BeanFactory
(또는 관련 수업에서) 콩을 찾을 수 없을 것이고 어떻게 콩을 찾을 수 있는지 확인할 수 있을 것입니다.
콩이 존재하지 않습니다. 등록되지 않았습니다.
아래 예제에서
@Configuration
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
ctx.getBean(Foo.class);
}
}
class Foo {}
우리는 유형에 대한 콩 정의를 등록하지 않았습니다.Foo
를 통해서 또는@Bean
법,@Component
스캔, XML 정의, 또는 다른 방법.BeanFactory
가 관리하는AnnotationConfigApplicationContext
따라서 요청한 콩을 어디서 얻을 것인지에 대한 표시가 없습니다.getBean(Foo.class)
을 던집니다. 위의 토막글은 다음과 같이 던집니다.
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.example.Foo] is defined
마찬가지로, 예외는 다음을 만족시키기 위해 노력하는 동안에 던져질 수 있었습니다.@Autowired
의존.예를들면,
@Configuration
@ComponentScan
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
}
}
@Component
class Foo { @Autowired Bar bar; }
class Bar { }
여기에는 다음에 대한 콩 정의가 등록되어 있습니다.Foo
해를 @ComponentScan
. 하지만 봄은 아무것도 몰라요Bar
. 따라서 자동 배선을 시도하는 동안 해당 빈을 찾지 못합니다.bar
야전의Foo
콩 예(a 안에 둥지를 틀었습니다)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.example.Bar] found for dependency [com.example.Bar]:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
콩 정의를 등록하는 방법은 여러 가지가 있습니다.
@Bean
a의 메소드@Configuration
계급이나<bean>
ML 구성으로@Component
(그리고 메타 annot화 등).@Repository
)을 통하여@ComponentScan
아니면<context:component-scan ... />
- 수동으로 통과
- 수동으로 통과
BeanDefinitionRegistryPostProcessor
...그리고 그 이상.
당신이 기대하는 콩이 제대로 등록되었는지 확인하세요.
일반적인 오류는 콩을 여러 번 등록하는 것입니다. 즉, 동일한 종류에 대해 위의 옵션을 혼합하는 것입니다.예를 들면 제가.
@Component
public class Foo {}
를 포함한 XML 구성.
<context:component-scan base-packages="com.example" />
<bean name="eg-different-name" class="com.example.Foo />
그러한 구성은 두 종류의 콩을 등록할 것입니다.Foo
, 이름있는 사람foo
그리고 또 다른 이름을 가진.eg-different-name
보다 더 콩을 것은 실수로 당신이 원하는 것보다 더 많은 콩을 등록하는 것은 아닌지 확인하세요.그래서 우리는...
XML 및 주석 기반 구성을 모두 사용하는 경우 다른 구성에서 하나를 가져오는지 확인합니다.XML이 제공합니다.
<import resource=""/>
자바는 주석을 제공합니다.
일치하는 단일 빈이 필요하지만 2개 이상 발견됨
같은 종류(또는 인터페이스)에 여러 개의 콩이 필요할 때가 있습니다.예를 들어 응용프로그램에서 MySQL 인스턴스와 Oracle 인스턴스의 두 데이터베이스를 사용할 수 있습니다.그런 경우에는 두개의DataSource
각각의 연결을 관리하기 위한 콩(간소화) 예를 들어, 다음과 같습니다.
@Configuration
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
System.out.println(ctx.getBean(DataSource.class));
}
@Bean(name = "mysql")
public DataSource mysql() { return new MySQL(); }
@Bean(name = "oracle")
public DataSource oracle() { return new Oracle(); }
}
interface DataSource{}
class MySQL implements DataSource {}
class Oracle implements DataSource {}
던지다
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [com.example.DataSource] is defined:
expected single matching bean but found 2: oracle,mysql
왜냐하면 두 콩이 모두 등록을 했기 때문입니다.@Bean
메소드는 다음의 요건을 충족했습니다. 즉, 둘 다 구현합니다.DataSource
두 를 지정할 이 예제에서 스프링은 두 가지를 구별하거나 우선 순위를 지정하는 메커니즘이 없습니다.하지만 그러한 메커니즘은 존재합니다.
설명서와 이 게시물에 설명된 대로 (및 XML에 해당)을 사용할 수 있습니다.이 변경으로
@Bean(name = "mysql")
@Primary
public DataSource mysql() { return new MySQL(); }
이전 토막글은 예외를 던지지 않고 대신 반환합니다.mysql
콩을
사용할 수도 있습니다.@Qualifier
(및 XML로 동등) 문서에 설명된 대로 빈 선택 프로세스에 대한 더 많은 제어권을 가질 수 있습니다.하는 동안에@Autowired
주로 유형별로 자동 배선에 사용됩니다.@Qualifier
이름으로 자동 배선할 수 있습니다.예를들면,
@Bean(name = "mysql")
@Qualifier(value = "main")
public DataSource mysql() { return new MySQL(); }
이제는 다음과 같이 주입될 수 있습니다.
@Qualifier("main") // or @Qualifier("mysql"), to use the bean name
private DataSource dataSource;
문제없이@Resource
는 옵션이기도 합니다.
잘못된 콩 이름 사용
콩을 등록하는 방법이 여러 가지가 있듯이 콩 이름을 짓는 방법도 여러 가지가 있습니다.
@Bean
가진.
이 콩의 이름 또는 복수인 경우 이 콩의 별칭입니다.지정되지 않은 상태로 두면 콩의 이름이 주석이 달린 메서드의 이름입니다.지정할 경우 메서드 이름이 무시됩니다.
<bean>
가 있습니다.id
빈에 대한 고유 식별자를 나타내는 속성과name
(XML) ID에서 하나 이상의 별칭을 만드는 데 사용할 수 있습니다.
@Component
그리고 그것의 메타 주석들은
이 값은 논리적 구성 요소 이름을 제안하는 것을 나타낼 수 있으며, 자동으로 감지된 구성 요소의 경우 스프링 빈으로 바꿉니다.
지정되지 않은 상태로 두면 주석이 달린 유형(일반적으로 유형 이름의 하위 낙타 대소문자 버전)에 대한 빈 이름이 자동으로 생성됩니다.예를들면MyClassName
된다myClassName
이름 그대로콩 이름은 대소문자를 구분합니다.또한 잘못된 이름/자본금은 일반적으로 다음과 같이 문자열로 언급되는 콩에서 발생합니다.@DependsOn("my BeanName")
또는 XML 구성 파일을 선택합니다.
@Qualifier
, 앞에서 언급했듯이, 콩에 더 많은 별칭을 추가할 수 있습니다.
콩을 지칭할 때는 반드시 올바른 이름을 사용해야 합니다.
보다 발전된 사례
프로필
콩 정의 프로파일을 사용하면 조건부로 콩을 등록할 수 있습니다. , 구체적으로,
하나 이상의 지정된 프로파일이 활성화된 경우 구성요소가 등록 대상임을 나타냅니다.
프로파일은 다음을 통해 프로그래밍적으로 활성화되거나 설정을 통해 선언적으로 활성화될 수 있는 명명된 논리적 그룹입니다.
spring.profiles.active
JVM 시스템 속성, 환경 변수 또는 웹 응용 프로그램에 대한 web.xml의 Servlet context 매개 변수로 속성을 지정합니다.프로파일은 주석을 통해 통합 테스트에서 선언적으로 활성화될 수도 있습니다.
예를 들어, 다음과 같은 경우에spring.profiles.active
속성이 설정되지 않았습니다.
@Configuration
@ComponentScan
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
System.out.println(Arrays.toString(ctx.getEnvironment().getActiveProfiles()));
System.out.println(ctx.getBean(Foo.class));
}
}
@Profile(value = "StackOverflow")
@Component
class Foo {
}
이렇게 하면 활성 프로파일이 표시되지 않고 다음과 같이 표시됩니다.NoSuchBeanDefinitionException
당분간은Foo
콩. 그때부터.StackOverflow
프로파일이 활성화되지 않았고 콩도 등록되지 않았습니다
대신에 제가 초기화를 하면ApplicationContext
해당 프로필을 등록하면서
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("StackOverflow");
ctx.register(Example.class);
ctx.refresh();
콩이 등록되어 있으며 반품/injected 가능합니다.
AOP 프록시
스프링은 고급 동작을 구현하기 위해 AOP 프록시를 많이 사용합니다.다음과 같은 예가 있습니다.
이를 위해 Spring은 두 가지 옵션을 선택할 수 있습니다.
- JDK의 Proxy 클래스를 사용하여 실행 시 bean의 인터페이스만 구현하고 모든 메서드 호출을 실제 bean 인스턴스에 위임하는 동적 클래스의 인스턴스를 만듭니다.
- CGLIB 프록시를 사용하여 인터페이스와 대상 빈의 구체적인 유형을 모두 구현하고 모든 메서드 호출을 실제 빈 인스턴스에 위임하는 동적 클래스의 인스턴스를 런타임에 생성합니다.
다음 JDK 프록시 예제를 사용합니다.@EnableAsync
의 채무 불이행proxyTargetClass
false
)
@Configuration
@EnableAsync
public class Example {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class);
System.out.println(ctx.getBean(HttpClientImpl.class).getClass());
}
}
interface HttpClient {
void doGetAsync();
}
@Component
class HttpClientImpl implements HttpClient {
@Async
public void doGetAsync() {
System.out.println(Thread.currentThread());
}
}
여기서 봄은 유형의 콩을 찾으려고 시도합니다.HttpClientImpl
우리가 찾을 것으로 기대하는 것은 그 유형에 명확한 주석이 달렸기 때문입니다.@Component
하지만, 대신에 우리는 예외를 받습니다.
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.example.HttpClientImpl] is defined
봄이 그를 감쌌습니다.HttpClientImpl
콩을 통해 그것을 노출시켰습니다.Proxy
구현만 하는 대상HttpClient
할 수 . 그래서 당신은 그것을 회수할 수 있었습니다.
ctx.getBean(HttpClient.class) // returns a dynamic class: com.example.$Proxy33
// or
@Autowired private HttpClient httpClient;
인터페이스에 프로그래밍하는 것이 항상 권장됩니다.그럴 수 없을 때는 Spring에게 CGLIB 프록시를 사용하라고 하면 됩니다.예를 들어, 을 사용하여 다음과 같이 설정할 수 있습니다.true
()EnableTransactionManagement
과 . ) . XML에도 .XML에는 동등한 구성 옵션도 있습니다.
ApplicationContext
IMT2000 3GPP - - 층 -링 MVC
봄은 당신이 건축할 수 있게 해줍니다.ApplicationContext
다른 사람들과의 예ApplicationContext
부모로서 예를 사용합니다. 자식 컨텍스트는 부모 컨텍스트에서 콩에 대한 액세스 권한을 갖지만, 그 반대는 사실이 아닙니다.이 게시물은 특히 Spring MVC에서 언제 이것이 유용한지에 대해 자세히 설명합니다.
일반적인 Spring MVC 응용 프로그램에서는 전체 응용 프로그램(루트)에 대한 컨텍스트와 특별히 (라우팅, 핸들러 메소드, 컨트롤러)에 대한 컨텍스트 두 가지를 정의합니다.자세한 내용은 여기에서 확인할 수 있습니다.
여기 공식 문서에도 아주 잘 설명되어 있습니다.
Spring MVC 구성의 일반적인 오류는 다음과 같은 루트 컨텍스트에서 WebMVC 구성을 선언하는 것입니다.@EnableWebMvc
주석이 달린@Configuration
수업이나<mvc:annotation-driven />
XML에서, 그러나 서블릿 맥락에서 콩.루트 컨텍스트가 서블릿 컨텍스트에 도달하여 빈을 찾을 수 없으므로 핸들러가 등록되지 않고 모든 요청이 404s로 실패합니다.당신은 볼 수 없을 것입니다.NoSuchBeanDefinitionException
, 하지만 효과는 같습니다.
적절한 맥락에서 콩이 등록되었는지 확인합니다. 즉, WebMVC에 등록된 콩으로 찾을 수 있는 곳(HandlerMapping
,HandlerAdapter
,ViewResolver
,ExceptionResolver
),).가장 좋은 해결책은 콩을 적절히 격리하는 것입니다.DispatcherServlet
모든 관련된 콩들이 그것의 맥락으로 들어가야 하도록 요청을 라우팅하고 처리하는 책임이 있습니다. 더ContextLoaderListener
, 루트 컨텍스트를 로드하는 경우 나머지 애플리케이션 요구사항인 서비스, 저장소 등을 초기화해야 합니다.
어레이, 컬렉션 및 맵
일부 알려진 유형의 콩은 봄에 의해 특별한 방식으로 취급됩니다.예를 들어, 다음의 배열을 주입하려고 하면MovieCatalog
들판으로
@Autowired
private MovieCatalog[] movieCatalogs;
봄은 모든 종류의 콩을 찾을 것입니다.MovieCatalog
, 배열로 감싸고 그 배열을 주입합니다.이것은 다음을 논의하는 Spring 문서에 설명되어 있습니다. 유사한 행동이 적용됩니다.Set
,List
,그리고.Collection
주사 목표물
일단은Map
주입 대상, 키 유형이 다음과 같다면 스프링도 이와 같이 동작합니다.String
를 들면, 있다면요. 예를 들어, 만약 당신이
@Autowired
private Map<String, MovieCatalog> movies;
봄은 모든 종류의 콩을 찾을 것입니다.MovieCatalog
a에 값으로 추가합니다.Map
, 거기에 해당하는 키가 그들의 콩 이름이 될 것입니다.
앞서 설명한 바와 같이 요청된 유형의 콩이 없다면 스프링은 다음과 같은 작업을 수행할 것입니다.NoSuchBeanDefinitionException
과 같은 의 빈(을하고 싶을 때도 하지만 때로는 다음과 같은 컬렉션 유형의 빈을 선언하고 싶을 때도 있습니다.
@Bean
public List<Foo> fooList() {
return Arrays.asList(new Foo());
}
주사를 놓는 겁니다
@Autowired
private List<Foo> foos;
이 예에서 스프링은 다음과 같이 고장납니다.NoSuchBeanDefinitionException
없기 때문에Foo
상황에 맞는 콩.하지만 당신은 원하지 않았잖나Foo
콩, 당신은 원하셨잖아요.List<Foo>
콩. 봄 4.3 이전에는.
자체적으로 집합/지도 또는 배열형으로 정의된 콩의 경우,
@Resource
는 특정 컬렉션 또는 배열 빈을 고유한 이름으로 지칭하는 미세 솔루션입니다.즉, 4.3 현재 수집/맵 및 배열 유형은 Spring's를 통해 일치시킬 수 있습니다.@Autowired
요소 유형 정보가 보존되는 한 유형 일치 알고리즘도 마찬가지입니다.@Bean
반환 형식 서명 또는 수집 상속 계층 구조입니다.이 경우 한정자 값을 사용하여 앞 단락에서 설명한 대로 동일한 유형의 집합 중에서 선택할 수 있습니다.
이것은 컨스트럭터, 세터, 필드 인젝션에 적합합니다.
@Resource
private List<Foo> foos;
// or since 4.3
public Example(@Autowired List<Foo> foos) {}
하지만, 그것은 실패할 것입니다.@Bean
즉법,법
@Bean
public Bar other(List<Foo> foos) {
new Bar(foos);
}
여기서 봄은 어떤 것도 무시합니다.@Resource
아니면@Autowired
방법에 주석을 다는 것, 왜냐하면 그것은@Bean
method, 따라서 문서에 설명된 동작을 적용할 수 없습니다.하지만 여러분은 봄의 표현 언어(SpEL)를 사용하여 콩의 이름을 부를 수 있습니다.위의 예에서, 당신은 다음을 사용할 수 있습니다.
@Bean
public Bar other(@Value("#{fooList}") List<Foo> foos) {
new Bar(foos);
}
이름이 붙은 콩을 가리키다fooList
주사를 놔주세요.
언급URL : https://stackoverflow.com/questions/39173982/what-is-a-nosuchbeandefinitionexception-and-how-do-i-fix-it
'prosource' 카테고리의 다른 글
Chrome 콘솔에서 전체 개체를 표시하는 방법 (0) | 2023.10.25 |
---|---|
파이썬에 불변 리스트가 있습니까? (0) | 2023.10.25 |
wp_signon()을 사용하여 워드프레스의 사용자 테이블 이외의 데이터를 사용하여 로그인하는 방법? (0) | 2023.10.25 |
AWS EC2 WordPress 사이트에 SSL을 설치하는 방법 (0) | 2023.10.25 |
WooCommerce에서 사용자 지정 제품 데이터 탭의 아이콘을 정의하는 방법 (0) | 2023.10.25 |