spring怎么获取全部的bean
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring怎么获取全部的bean相关的知识,希望对你有一定的参考价值。
通过xml配置文件 bean配置在xml里面,spring提供多种方式读取配置文件得到ApplicationContext. 第一种方式:FileSystemXmlApplicationContext 通过程序在初始化的时候,导入Bean配置文件,然后得到Bean实例: ApplicationContext ac = new FileSystemXmlApplicationContext(applicationContext.xml) ac.getBean(beanName); 第二种方式:WebApplicationContextUtil 在B/S系统中,通常在web.xml初始化bean的配置文件,然后由WebAppliCationContextUtil得到ApplicationContext.例如: ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc); ApplicationContext ctx = 参考技术A 这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况。不难理解对于通过web.xml配置启动的Spring来说也一定是里面实现了此方法。本回答被提问者采纳 参考技术B 通过xml配置文件 bean配置在xml里面,spring提供多种方式读取配置文件得到ApplicationContext. 第一种方式:FileSystemXmlApplicationContext 通过程序在初始化的时候,导入Bean配置文件,然后得到Bean实例: ApplicationContext ac = new FileSystemXmlApplicationContext(applicationContext.xml) ac.getBean(beanName); 第二种方式:WebApplicationContextUtil 在B/S系统中,通常在web.xml初始化bean的配置文件,然后由WebAppliCationContextUtil得到ApplicationContext.例如: ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc); ApplicationContext ctx =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<><><><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
以上是关于spring怎么获取全部的bean的主要内容,如果未能解决你的问题,请参考以下文章