- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
请在Spring中解释有关NoSuchBeanDefinitionException
异常的以下内容:
这是什么意思?
在什么情况下会抛出?
我该如何预防?
这篇文章旨在对使用Spring的应用程序中NoSuchBeanDefinitionException
的出现进行全面的问答。
最佳答案
javadoc of NoSuchBeanDefinitionException
解释
当请求BeanFactory
的bean实例时引发异常
它找不到定义。这可能表示不存在
bean,非唯一bean或手动注册的单例实例
没有关联的bean定义。BeanFactory
基本上是表示Spring's Inversion of Control container的抽象。它在内部和外部向您的应用程序公开bean。当无法找到或检索这些bean时,将抛出NoSuchBeanDefinitionException
。
以下是BeanFactory
(或相关类)无法找到Bean的简单原因,以及如何确保找到它的原因。
Bean不存在,尚未注册
在下面的示例中
@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
扫描,XML定义或任何其他方式为
@Component
类型注册bean定义。因此,由
BeanFactory
管理的
AnnotationConfigApplicationContext
无法指示从哪里获取
getBean(Foo.class)
请求的bean。上面的代码片段
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
注册了bean定义。但是Spring对
Bar
一无所知。因此,在尝试自动装配
bar
bean实例的
Foo
字段时,它找不到对应的bean。抛出(嵌套在
UnsatisfiedDependencyException
内)
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
类中的
@Configuration
方法或XML配置中的
<bean>
@Component
或
@Repository
中的
@ComponentScan
(及其元注释,例如
<context:component-scan ... />
)
GenericApplicationContext#registerBeanDefinition
手动
BeanDefinitionRegistryPostProcessor
手动
@Component
public class Foo {}
<context:component-scan base-packages="com.example" />
<bean name="eg-different-name" class="com.example.Foo />
Foo
的bean,一个名称为
foo
,另一个名称为
eg-different-name
。确保您不会意外地注册比所需数量更多的bean。这导致我们...
<import resource=""/>
@ImportResource
注释。
DataSource
bean来管理与每个bean的连接。对于(简化的)示例,以下内容
@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
方法注册的两个bean都满足
BeanFactory#getBean(Class)
的要求,即。它们都实现
DataSource
。在这个例子中,Spring没有机制来区分或区分两者。但是存在这样的机制。
@Primary
和
documentation中所述使用
this post(及其在XML中的等效项)。有了这个改变
@Bean(name = "mysql")
@Primary
public DataSource mysql() { return new MySQL(); }
mysql
bean。
@Qualifier
(及其在XML中的等效项)来更好地控制bean选择过程,如
documentation中所述。虽然
@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
具有
name
<bean>
具有
id
属性以表示bean的唯一标识符,并且
name
可用于创建一个或多个(XML)ID中非法的别名。
@Component
及其元注释具有
value
@Qualifier
使您可以向bean添加更多别名。
@Profile
,具体地说,
ConfigurableEnvironment.setActiveProfiles(java.lang.String...)
或
spring.profiles.active
属性设置为JVM来声明式地
@ActiveProfiles
在集成测试中以声明方式激活
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
bean抛出
Foo
。由于
StackOverflow
配置文件未激活,因此未注册Bean。
ApplicationContext
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("StackOverflow");
ctx.register(Example.class);
ctx.refresh();
@Transactional
@Cacheable
@Async
和
@Scheduled
@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
的bean,因为该类型显然用
@Component
进行了注释。但是,相反,我们得到了一个例外
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.example.HttpClientImpl] is defined
HttpClientImpl
bean,并通过仅实现
Proxy
的
HttpClient
对象将其公开。所以你可以用
ctx.getBean(HttpClient.class) // returns a dynamic class: com.example.$Proxy33
// or
@Autowired private HttpClient httpClient;
@EnableAsync
,可以将
proxyTargetClass
设置为
true
。相似的注释(
EnableTransactionManagement
等)具有相似的属性。 XML也将具有等效的配置选项。
ApplicationContext
层次结构-Spring MVC
ApplicationContext
与其他
ApplicationContext
实例作为父级来构建
ConfigurableApplicationContext#setParent(ApplicationContext)
实例。子上下文可以在父上下文中访问bean,但事实并非如此。
This post详细介绍了何时使用此功能,尤其是在Spring MVC中。
DispatcherServlet
(路由,处理程序方法,控制器)。您可以在此处获得更多详细信息:
@EnableWebMvc
带注释的
@Configuration
类或XML中的
<mvc:annotation-driven />
声明WebMVC配置,而在servlet上下文中使用
@Controller
Bean声明WebMVC配置。由于根上下文无法进入Servlet上下文以查找任何bean,因此没有注册任何处理程序,并且所有请求均失败,并带有404。您不会看到
NoSuchBeanDefinitionException
,但是效果是一样的。
HandlerMapping
,
HandlerAdapter
,
ViewResolver
,
ExceptionResolver
等)中可以找到它们。最好的解决方案是正确隔离豆。
DispatcherServlet
负责路由和处理请求,因此所有相关的bean应该进入其上下文。加载根上下文的
ContextLoaderListener
应该初始化应用程序其余需要的所有bean:服务,存储库等。
MovieCatalog
数组注入字段
@Autowired
private MovieCatalog[] movieCatalogs;
MovieCatalog
类型的bean,将它们包装在一个数组中,然后注入该数组。
Spring documentation discussing @Autowired
中对此进行了描述。类似的行为适用于
Set
,
List
和
Collection
注入目标。
Map
注入目标,如果键类型为
String
,Spring也将以这种方式运行。例如,如果您有
@Autowired
private Map<String, MovieCatalog> movies;
MovieCatalog
类型的bean,并将它们作为值添加到
Map
,其中对应的键将是其bean名称。
NoSuchBeanDefinitionException
。但是,有时候,您只想声明这些集合类型的bean,例如
@Bean
public List<Foo> fooList() {
return Arrays.asList(new Foo());
}
@Autowired
private List<Foo> foos;
NoSuchBeanDefinitionException
,因为上下文中没有
Foo
bean。但是您不想要
Foo
bean,而是想要
List<Foo>
bean。
Before Spring 4.3, you'd have to use @Resource
@Resource
是一个很好的解决方案,指的是具体
@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
方法,因此无法应用文档中描述的行为。但是,您可以使用Spring Expression Language(SpEL)来按其名称引用bean。在上面的示例中,您可以使用
@Bean
public Bar other(@Value("#{fooList}") List<Foo> foos) {
new Bar(foos);
}
fooList
的bean并将其注入。
关于java - 什么是NoSuchBeanDefinitionException,我该如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40285908/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!