2017-03-25 85 views
1

我想爲所有控制器調用一個公共服務來獲取一個具有一些公共對象的commmon ModelAndView對象。實例化@postconstruct內部的@autowired bean內部控制器,spring

所以我爲所有控制器創建了一個超類 - BaseController,並且我通過調用一個方法initCommonData啓動了BaseController的構造函數中的通用模型對象,該方法使用@Autowired bean CommonDataService,它不存在於對象的構建時間和返回null,所以我應該做的是在構造函數中獲得@autowired依賴。

僅供參考 - 我使用這種常見的服務和常用數據來獲取一些商品數據,這些商品數據將用於網站頁眉和頁腳中的每個jsp。 因此,如果在不調用每種控制器方法中的通用服務的情況下做到這一點,可以在每個控制器中建議。 這裏是我的代碼 - BaseController

@Controller 
public class BaseController { 

@Autowired 
private CommonDataService commonDataService; 

protected ModelAndView model; 

public BaseController() { 
    this.initCommonData(); 
} 

public void initCommonData(){ 
    this.model = new ModelAndView(); 
    this.model.addObject("headerData",commonDataService.getHeaderData()); 
    this.model.addObject("footerData",commonDataService.getFooterData()); 
} 

子控制器 -

@Controller 
public class HomeController extends BaseController { 

@Autowired 
CategoryService categoryService; 

@Autowired 
CompanyService companyService; 

@RequestMapping(value = { "", "/", "home" }) 
public ModelAndView homePage() { 
    model.setViewName("home"); 
    . 
    . 
    . 
    model.addObject("name", value); 
    model.addObject("name2", value2); 
    return model; 
} 

CommonServiceClass -

@Service 
public class CommonDataService { 

@Autowired 
CompanyService companyService; 

@Autowired 
CategoryService categoryService; 

@Cacheable 
public List<Category> getHeaderData(){ 
    return categoryService.getTopCategoryList(); 
} 

@Cacheable 
public List<Company> getFooterData(){ 
    return companyService.getTopCompanyList(); 
} 

請建議,如果有這樣做的任何其他的好辦法,讓普通的數據從服務器到jsp。

+0

你提到'@ PostConstruct'在您的標題,這是一個答案,你的麻煩,那麼你爲什麼不使用它? – Andreas

+0

我試着@PostConstruct的解決方案,但它沒有被調用.. 發現了一些循環依賴問題,(做一些谷歌搜索後) –

+0

使用postgui建議由javaguy,現在工作正常.. 不知道我在做什麼當我在接受的答案中使用javaguy的建議使用postconstruct時發生錯誤,並且postconstruct沒有被調用,, –

回答

1

@Andreas建議的是最好的解決方案,即將BaseController標記爲abstract並使用@Postconstruct。這使得完美scense因爲BaseController本身不擁有你的情況的任何URL映射,所以不要將其標記爲@Controller

因爲任何原因,如果你正在尋找其他的選擇,你可以考慮標記您的BaseController@Component和使用@Postconstruct用於initCommonData這樣一旦BaseController豆已經被Spring容器裝載這個方法會被自動調用:

@Component 
public class BaseController { 

    @Autowired 
    private CommonDataService commonDataService; 

    protected ModelAndView model; 

    @Postconstruct 
    public void initCommonData(){ 
     this.model = new ModelAndView(); 
     this.model.addObject("headerData",commonDataService.getHeaderData()); 
     this.model.addObject("footerData",commonDataService.getFooterData()); 
    } 
} 
+0

正確地移除對'initCommonData()'的構造函數調用和拼寫'@ PostConstruct'。 – Andreas

+0

使用postconstruct按照你建議的@javaguy,現在工作正常.. 不知道我在做什麼錯誤,當我在使用postconstruct時,由javaguy在接受的答案中建議,並且postconstruct沒有被調用,, –

1

首先,從你的基類中刪除@Controller。您甚至可以讓課程abstract幫助指示/記錄它必須被分類。

接下來,請不要從構造函數調用initCommonData()。在創建對象之前,Spring不能注入字段值,所以Spring在構造函數完成之前無法在commonDataService中進行連接。

相反,註釋initCommonData()@PostConstruct

public class BaseController { 

    @Autowired 
    private CommonDataService commonDataService; 

    protected ModelAndView model; 

    @PostConstruct 
    public void initCommonData(){ 
     this.model = new ModelAndView(); 
     this.model.addObject("headerData",commonDataService.getHeaderData()); 
     this.model.addObject("footerData",commonDataService.getFooterData()); 
    } 
+0

如果刪除@ Controller,spring無法檢測到該類注入依賴關係 – developer

+0

另外,由於需要單例實例,因此無法將該類設置爲抽象類 – developer

+0

@javaguy對於其他的「@ Controller」類,該類是一個*基類*擴展,例如'HomeController'。它本身不是一個Spring bean。查看有問題的代碼。 – Andreas