標籤:現在 frame ESS get rri ted 首字母 raise 註解
具體問題請看 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 實現它,試試,,日,,真的正常了。。
@Servicepublic 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"; }[email protected]<>>>>>>>>>>>>>>>>>>>>>>>after<><><><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
spring 的 ApplicationContext.getBean(type) 無法擷取bean,報錯