【问题标题】:Spring-Wicket: optional but named bean still requiredSpring-Wicket:可选但仍需要命名 bean
【发布时间】:2012-06-26 16:22:20
【问题描述】:

考虑以下(检票口)代码:

@SpringBean(required=false)
private StatusCheckService service;

在我的用例中,我的上下文中没有 StatusCheckService 类型的 bean。 这不是问题,它被标记为可选,因此(检票口)页面将正常初始化。

但是:

@SpringBean(name = "statusCheckService", required=false)
private StatusCheckService service;

这失败了:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'statusCheckService' is defined
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:529)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095)
     at org.springframework.beans.factory.support.AbstractBeanFactory.isSingleton(AbstractBeanFactory.java:400)
     at org.springframework.context.support.AbstractApplicationContext.isSingleton(AbstractApplicationContext.java:1113)
     at org.apache.wicket.spring.SpringBeanLocator.isSingletonBean(SpringBeanLocator.java:100)
     at org.apache.wicket.spring.injection.annot.AnnotProxyFieldValueFactory.getFieldValue(AnnotProxyFieldValueFactory.java:140)

我希望这没有什么区别。好的,没有具有这样名称的 bean,但我将其标记为可选,为什么会出现异常?有没有办法解决这个问题?

【问题讨论】:

  • 如果您省略名称,它是否有效?
  • 嗨,Bert,是的,那么我在启动时没有收到错误消息。这是一个相当复杂的用例,很难用几句话来解释。上面的代码驻留在一个网页中,可以在几个 (17) wicket 应用程序中使用。其中一些将定义一个 StatusCheckService(使用添加到服务 bean 声明的 Spring 名称别名),而另一些则没有。甚至不确定这是 Spring 还是 Wicket 问题。
  • 查看堆栈跟踪,它看起来比检票口更具弹性。但你永远不知道。

标签: spring dependency-injection wicket wicket-1.5


【解决方案1】:

通过eclipse中的用法搜索,可以看到唯一一次查询注解需要的值是在AnnotProxyFieldValue的第215行:

if (names.isEmpty())
{
    if (annot.required())
    {
        throw new IllegalStateException("bean of type [" + clazz.getName() + "] not found");
    }
    return null;
}

这里你可以看到@SpringBean注解的'required'字段只有在names列表(在函数中设置较高)为空的情况下才使用...

这解释了您遇到的行为,因为当您不指定名称时,名称列表为空(因为它找不到您的类),并且返回 null。但是,当您确实指定了名称时,它不会费心尝试查看该类是否存在,因此会将您提供的类名发送给 spring 进行查找,当它找不到该类时会继续抱怨。

这可能是一个错误,具体取决于设计人员的意图,我个人认为,如果您已指定该字段不是必需的,则该功能应尽早返回...如果您同意,则可以考虑放入 jira 票以快速启动.

至于解决方案,您并没有过多地提及您的用例,以及为什么您需要设置名称,即使您不需要注入 bean。但是假设您这样做是为了根据某些条件动态注入 bean,您可以执行以下操作:(未经测试)

在注入 SpringBean 的类中,替换:

@SpringBean(name="statusCheckService", required=false)
private StatusCheckService service;

与:

MyCustomSpringBeanInjector injectedService;

然后 MyCustomSpringBeanInjector 类是这样的:

import org.apache.wicket.injection.Injector;
import org.apache.wicket.spring.injection.annot.SpringBean;

public class MyCustomSpringBeanInjector
{
    @SpringBean public StatusCheckService service;

    public MyCustomSpringBeanInjector()
    {
        Injector.get().inject(this);
    }
}

然后回到注入 SpringBean 的类中,输入如下内容:

if(statusCheckServiceRequired)
    injectedService = new MyCustomSpringBeanInjector();

并替换“服务”。必要时使用“injectedService.service”。

显然,这是一个 qwik-e 修复我的头顶,我确信有更好的方法,但你明白了! :)

祝你好运!

【讨论】:

  • 谢谢,这恰好与我解决(或更确切地说是解决)它的方式相似。我创建了一个包含可选依赖项的包装器。我会考虑为此提出错误报告,因为正如您所说,我希望支票能早日返回。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-07
  • 2018-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-30
相关资源
最近更新 更多