首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >应用上下文bean

应用上下文bean
EN

Stack Overflow用户
提问于 2011-03-07 20:52:41
回答 3查看 4.8K关注 0票数 2

我正在尝试从应用程序上下文中提取bean。

所以我定义了类:

代码语言:javascript
复制
public class ApplicationContextProvider implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    public void setApplicationContext(ApplicationContext _applicationContext) throws BeansException {
        applicationContext = _applicationContext;

    }

}

在我的applicationContext.xml里

代码语言:javascript
复制
<bean id="workflowService" class="com.mycompany.util.WorkflowService">
    <bean id="applicationContextProvider" class="com.mycompany.util.ApplicationContextProvider"></bean>
   <context:annotation-config />

但是,在我的代码中,当我尝试:

代码语言:javascript
复制
WorkflowService service  = (WorkflowService) ApplicationContextProvider.getApplicationContext().getBean("workflowService");

我得到:

java.lang.ClassCastException:不能将$Proxy40转换为com.mycompany.util.WorkflowService

编辑的

WorkflowService代码:

代码语言:javascript
复制
public class WorkflowService implements Serializable {
   ...
   @PostConstruct
       public void init() {
   }
   ...
   @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
       public Collection<lData> findData(Integer contractId) {
   }    
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-03-07 20:57:04

我猜WorkflowService是一个实现至少一个接口的类(您没有提供足够的代码)。您正在尝试从Spring中查找确切的类,而您应该请求其中一个接口。

这是因为Spring大部分时间都将bean封装在几个代理(例如事务性代理)中。如果类实现至少一个接口,则生成的代理实现所有接口,但不能转换为原始类。如果类没有实现任何接口(对于重量级服务来说通常被认为是一种不好的实践,但值得怀疑),Spring将使用来自原始类的CGLIB子类。在这种情况下,代码将是有效的。

票数 4
EN

Stack Overflow用户

发布于 2011-03-07 22:00:41

你的问题是:

代码语言:javascript
复制
WorkflowService implements Serializable

Spring生成的任何代理都将实现类所做的所有接口--在本例中是Serializable,这几乎肯定不是您想要的。

您应该做的是从WorkflowService中提取一个新的接口,其中包括findData方法(让我们称之为WorkflowOperations)。通过实现该接口,您将能够对该接口进行强制转换。

代码语言:javascript
复制
public interface WorkflowOperations {
    Collection<lData> findData(Integer contractId);
}


public class WorkflowService implements WorkflowOperations {

    ...
    @PostConstruct
        public void init() {
    }
    ...
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
        public Collection<lData> findData(Integer contractId) {
    }

}

然后:

代码语言:javascript
复制
 WorkflowOperations service  = (WorkflowOperations) ApplicationContextProvider.getApplicationContext().getBean("workflowService");

您可能还应该从Serializable中删除WorkflowService。您几乎肯定不需要这个,像这样序列化Spring是没有意义的。如果您只是根据习惯添加了Serializable,那么就删除它(并摆脱这个特定的习惯)。

票数 4
EN

Stack Overflow用户

发布于 2011-03-07 22:53:18

您正在用@Transactional注释您的服务,所以Spring使用事务性JDK动态代理包装您的服务bean,该代理实现与您的bean相同的接口,但不是WorkflowService。这就是当您尝试将ClassCastException赋值给WorkflowService变量时得到它的原因。我认为有两种可能的解决办法:

  • 与您的业务方法指定一个接口WorkflowService,并在WorkflowServiceImpl类中实现它。然后,在Spring上下文中,将bean定义从WorkflowService更改为WorkflowServiceImpl。这是我推荐的,既作为一般设计原则,也特别是在Spring环境中工作: Spring喜欢interfaces.
  • In您的Spring上下文,在<tx:annotation-driven/>元素中添加proxy-target-class="true",以便通过子类强制Spring实现代理,从而使proxy instanceof WorkFlowService成为真。我觉得这个解决方案更脏。还请注意,您以这种方式添加了CGLIB的依赖项。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5225104

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档