zoukankan      html  css  js  c++  java
  • 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<><><><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    

      



  • 相关阅读:
    [GoogleAppEngine]编译问题-locale zh_CN
    [Android]Webview中JS接口调用Java-版本问题
    [HTTP基础]3. HTTP链接
    [WebView]简单总结
    [HTTP基础]1.网络开发必备的HTTP协议知识
    [HTTP基础]2.Http和Socket区别
    [HTTP]Android抓包方法(Wireshark)
    [Android]Process&Thread-基本原理
    [Android]Thread两种实现方法
    [Android]消息队列模型——Thread,Handler,Looper,Massage Queue
  • 原文地址:https://www.cnblogs.com/zhangchenglzhao/p/9337594.html
Copyright © 2011-2022 走看看