具體問題請看 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<><><><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>