簡體   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