spring 的 ApplicationContext.getBean(type) 無法獲取bean,報錯


具體問題請看   https://q.cnblogs.com/q/108101/

研究了兩天: 經過上文中的排除法: 造成問題的原因是要獲取的bean 中 有被切入的方法。。

  就是可能該類會使用反射生成一個類。。

怎么測試呢?

  想到 @Autowired  和 @Resource  這兩個注解。。

他們會通過 類型 和 名稱去找容器中對應 的 bean 。。

於是在controller 中使用 這個注解 注入 zaService; 

報錯了  : 

  

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'zaSerivce' is expected to be of type 'com.mytest.context.impl.ZaSerivce' but was actually of type 'com.sun.proxy.$Proxy15'
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.checkBeanNotOfRequiredType(DefaultListableBeanFactory.java:1510)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.checkBeanNotOfRequiredType(DefaultListableBeanFactory.java:1517)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1489)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
	... 67 more

  這就說明了兩個問題: 1. 為什么 byTpe 無法獲取bean ,,因為它的類型根本就不是  com.mytest.context.impl.ZaSerivce 而是    com.sun.proxy.$Proxy15

            2.  byName 雖然可以獲取但是會發現它的類型也已經不是 ZaService 了。。 

ApplicationContext context =  ApplicationContextUtils.context;
        ZaService z = (ZaService) context.getBean("zaService");

java.lang.ClassCastException: com.sun.proxy.$Proxy15 cannot be cast to com.mytest.context.impl.ZaService

  

 

 

解決辦法: 1. 通過byType 獲取bean 時參數傳 接口類的class ..    不足: 只能有一個實現類。

      2.  byName 可以正常傳參數 bean 的首字母小寫。。 但是只能轉換為接口類 

          IZaService z = (IZaService) context.getBean("zaService");

 

  而我的業務參數是  實現類的全路徑名,所以特別適合 class.forName();  然后 byType .. 可惜用不了。。 只能退而求其次了把參數 調整為 接口的全路徑名。。但是只能有一個實現類。。

至於為什么被 切 的 類 在spring 容器中的 type 變了, 那可能要考慮代理反射,個人觀點是 spring 默認使用jdk 動態代理,這種方式會生成一個全新的類,比如本例的

$Proxy15, 然后通過這個代理類方法前后編入代碼,然后調用原始類的方法。。 說遠了,。。。。 

注意 : spring 還有一種代理方式: CGLIB 是不會生成新的類,那如果不生成新的類,就不會出現上述的問題了,,現在驗證下(spring 對沒有實現接口的類的代理方式是 CGLib )

我們只要把 IZaServiec 去掉就行了不要Zaserivce 實現它,試試,,日,,真的正常了。。
      
@Service
public class ZaService  {

    @TestAnn
    /*@Override*/
    public void aa() {

    }
}


@ResponseBody
    @RequestMapping("/context")
    public String context(){
        ApplicationContext context =  ApplicationContextUtils.context;
        ZaService z = (ZaService) context.getBean(ZaService.class);
        System.out.println(z);
        z.aa();
        return "context";
    }

com.mytest.context.impl.ZaService@7cb0dfee
<>>>>>>>>>>>>>>>>>>>>>>>after<><><><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM