繁体   English   中英

应用上下文bean

[英]Application context bean

我试图从应用程序上下文中提取bean。

所以我定义了类:

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中

<bean id="workflowService" class="com.mycompany.util.WorkflowService">
    <bean id="applicationContextProvider" class="com.mycompany.util.ApplicationContextProvider"></bean>
   <context:annotation-config />

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

WorkflowService service  = (WorkflowService) ApplicationContextProvider.getApplicationContext().getBean("workflowService");

我明白了:

java.lang.ClassCastException:$ Proxy40无法强制转换为com.mycompany.util.WorkflowService

编辑

WorkflowService代码:

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

你的问题是这样的:

WorkflowService implements Serializable

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

你应该做的是从WorkflowService提取一个新接口,它包含findData方法(我们称之为WorkflowOperations )。 通过实现该接口,您将能够转换到该接口,例如

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) {
    }

}

接着:

 WorkflowOperations service  = (WorkflowOperations) ApplicationContextProvider.getApplicationContext().getBean("workflowService");

您可能还应该从WorkflowService删除Serializable 你几乎肯定不需要这个,像这样序列化Spring bean是没有意义的。 如果您刚刚添加了Serializable的习惯,那么将其删除(并摆脱这种特殊习惯)。

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

这是因为Spring大部分时间都将bean包装在几个代理中(例如事务代理)。 如果类实现至少一个接口,则生成的代理实现所有接口,但不能转换为原始类。 如果类没有实现任何接口(通常被认为是重量级服务的不良做法,尽管有问题),Spring将使用原始类的CGLIB子类。 在这种情况下,您的代码将是有效的。

您正在使用@Transactional注释您的服务,因此Spring使用事务JDK动态代理来包装您的服务bean,该代理实现与您的bean相同的接口,但不是WorkflowService 这就是当您尝试将其分配给WorkflowService变量时获得ClassCastException原因。 我看到两种可能的解决方案

  • 使用业务方法指定WorkflowService接口,并在WorkflowServiceImpl类中实现它。 然后在Spring上下文中将bean定义从WorkflowService更改为WorkflowServiceImpl 这是我推荐的,作为一般设计原则,特别是在Spring环境中工作:Spring喜欢接口。

  • 在Spring上下文中,将proxy-target-class="true"<tx:annotation-driven/>元素中,以强制Spring通过子类化实现代理,以便proxy instanceof WorkFlowService为true。 我觉得这个解决方案比较脏。 另请注意,您通过这种方式添加CGLIB依赖项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM