开发者社区> 问答> 正文

问一个Spring注入Bean的问题?报错

大家都知道可以通过spring的xml文件的形式来管理Bean,通常情况下,比如有一个类叫做com.athena.beans.MyBean,那么我们可以在xml文件中这样配置:


<bean id="myBean" class="com.athena.beans.MyBean">
然后在需要使用该Bean的java类中,可以使用@Resource等注解来让Spring帮助注入该Bean的实例。


一般,通过bean节点配置后生成的实例都是class属性值中类的一个对象,也就是说上面配饰的MyBean,在生成后的实例,肯定是MyBean类型的。

但有下面的一个配置让我很迷茫:


<bean id="properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    	<property name="location" value="classpath:prop.properties"/>
    </bean>
看到,上面的class属性中的类是:
PropertiesFactoryBean
而生成的类型却是:Properties类型,它的使用代码如下:
@Resource
 private Properties properties;
而我原以为应该这样使用:

@Resource
private PropertiesFactoryBean properties;
也就是说,properties的类型应该是在xml中配置时候的class值的类型才对。。。

但实际使用的时候会报错,只有当把它声明为Properties类型的时候才正确。。。。

我知道可能是Spring对于FactoryBean这样的类可能有特殊处理,但不知道是如何实现的,求讲解,求思路!

多谢

展开
收起
爱吃鱼的程序员 2020-06-22 14:51:26 513 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB

    自己顶一下。。求解释

    如果容器发现一个beanclass是一个FactoryBean实现类,他仍然会是实例化这个FactoryBean,对他进行注入,但实际的bean对象则是是由这个FactoryBean实例来创建,除了创建实例的方法,FactoryBean本身有方法返回他创建的实例的类型和表示创建的实例是否是单例。

    更多细节,建议你在自己实现的FactoryBean里面打上断点调试,沿着调用栈查看Spring的源代码比口头问好很多。

    回复<aclass='referer'target='_blank'>@雅典娜拉:eclipse上,FactoryBean的那三个方法随便一个查他们的调用者就有结果了...刚才怕他是反射所以说要debug,结果直接调用就更省事了回复<aclass='referer'target='_blank'>@逝水fox:额,,,好厉害,,,能告诉我你是从哪个类开始找起的么?回复<aclass='referer'target='_blank'>@雅典娜拉:其实用IDE的话很好找的,调试都不需要"iif(beanInstanceinstanceofFactoryBean&&!isFactoryType){"org.springframework.beans.factory.support.StaticListableBeanFactory的代码里面回复<aclass='referer'target='_blank'>@逝水fox:恩,好吧,我试试,不过它的类结构很复杂。。。不过你也为我提供了一种新的思路,多谢指点回复<aclass='referer'target='_blank'>@雅典娜拉:你问的是Spring的实现细节,觉得他是特殊处理,那就打断点调试看什么东西调用你的FactoryBean来生成bean实例的,再在周围找找就会找到特殊处理的证据,细节这些东西看别人说还不如自己看源代码调试看得明白。<preclass="brush:java;toolbar:true;auto-links:false;">publicclassPropertiesFactoryBeanextendsPropertiesLoaderSupportimplementsFactoryBean<Properties>,InitializingBean<imgsrc="http://www.oschina.net/js/ke/plugins/emoticons/images/28.gif"alt=""/>我也说不清楚等别人解答

    应该是做特殊处理了。返回的时候都给的是<spanstyle="background-color:#F6F6F6;font-family:'CourierNew',Arial;font-size:9pt;line-height:1.5;">Properties

    <preclass="brush:java;toolbar:true;auto-links:false;">publicclassPropertiesFactoryBeanextendsPropertiesLoaderSupportimplementsFactoryBean<Properties>,InitializingBean{privatebooleansingleton=true;privatePropertiessingletonInstance;<preclass="brush:java;toolbar:true;auto-links:false;">publicClass<Properties>getObjectType(){returnProperties.class;}

    不要一味的套规则,要理解原理,你可以去了解下spring的bean创建方式,我个人理解的也许和别人常说的pring的bean几种创建方式可能不一样,我理解的有三种方式

    1、构造方法

    2、工厂bean(静态方法、实例方法、FactoryBean接口)

    3、代理(使用jdk代理或者类似CGlib库。例如:事务处理,spring通过aop方式产生bean的代理对象)

    恩。。。你的回答对我帮助很大,再次感谢!恩,其实我也一直在尝试着去理解原理,要不然也就不会问这个问题了。多谢指点!


    <preclass="brush:java;toolbar:true;auto-links:false;">@Resource('&properties')privatePropertiesFactoryBeanproperties;

    这样子说不定能得到~之所以叫FactoryBean,就因为是用它来生成Bean的,默认情况下,如果一个Bean是FactoryBean,Spring是会返回其生成的Bean,而不是工厂本身,如果想要得到工厂本身,需要在ID前加&.

    上面这样子不知道行不行,但<spanstyle="font-family:Helvetica,Tahoma,Arial,sans-serif;font-size:14px;line-height:25.1875px;background-color:#FFFFFF;">factory.getBean('&properteis')应该是可以获取到FactoryBean的。

    一般也很少会用到FactoryBean。


    前面加了个“&”有啥特殊作用吗?<divclass="ref">

    引用来自“梦无涯”的答案

    <divclass=ref_body>


    <preclass="brush:java;toolbar:true;auto-links:false;">@Resource('&properties')privatePropertiesFactoryBeanproperties;

    这样子说不定能得到~之所以叫FactoryBean,就因为是用它来生成Bean的,默认情况下,如果一个Bean是FactoryBean,Spring是会返回其生成的Bean,而不是工厂本身,如果想要得到工厂本身,需要在ID前加&.

    上面这样子不知道行不行,但<spanstyle="font-family:Helvetica,Tahoma,Arial,sans-serif;font-size:14px;line-height:25.1875px;background-color:#FFFFFF;">factory.getBean('&properteis')应该是可以获取到FactoryBean的。

    一般也很少会用到FactoryBean。


    哦。原来如此。。多谢指点这个是工厂bean实现了FactoryBean<Properties>,实际的返回对象是getObject方法Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。
    当配置文件中<bean>的class属性配置的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。

    <arel="nofollow">http://wenku.baidu.com/link?url=N0nQvLfRJ2w-InrUHOiXL_dvl5ecsxg0k7GCH6Eh8EEBCYAGQyyU3-tJ8Qwt21VLD3VJxHVLCKppopIVZGGH4yCNPcNJnfqgV09oNTWiLbG

    这个文章可以帮助你理解的!!!

    谢谢

    2020-06-22 14:51:44
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧 立即下载
微服务架构模式与原理Spring Cloud开发实战 立即下载
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载