Spring的FactoryBean接口探秘

今天接触到一个新项目,杰夫接口对外暴露一个接口:

<!-- 发布服务 alias可以改成自己的 -->
<jsf:provider id="puDaoDataService" interface="com.jd.jrdp.exts.server.PuDaoDataService" alias="${jsf.alias}"
ref="MapServiceProxy" server="jsf" timeout="20000">
</jsf:provider>
public interface PuDaoDataService extends CommonMapExternalService

但是PuDaoService只是一个单纯的接口,没有发现一个实现它的类(类似于mybatis只有接口没有实现类),并且实现类的参数里配置了一个“MapServiceProxy”,通过查找配置文件,这个id对应配置如下:

<!-- 动态代理服务类 -->
<bean id="MapServiceProxy" class="com.jd.jrdp.exts.common.support.CommonExternalServiceFactoryBean">
<!-- 拦截器,注:可以没有 -->
<property name="interceptors">
        <list>
<!--<ref bean="logInterceptor"/>-->
</list>
    </property>
<!-- 被调用的处理类,需和目标接口有完全相同的方法 -->
<property name="target" ref="DefaultExternalServiceRouter"/>
<!-- 被代理的目标接口 -->
<property name="targetInterface" value="com.jd.jrdp.exts.server.PuDaoDataService"/>
</bean>

这个类“CommonExternalServiceFactoryBean”并没有实现PuDaoDataService后者他的父接口,那是怎么注入到IOC里面去呢,后来发现CommonExternalServiceFactoryBean实现了FactoryBean接口

public class CommonExternalServiceFactoryBean implements FactoryBean<BaseCommonService>, InitializingBean, DisposableBean

里面自定义了getObject方法和getObjectType()方法,原来

假设我们定义了一个FactoryBean,名为myFactoryBean,当我们调用getBean(“myFactoryBean”)方法时返回的并不是这个FactoryBean,而是这个FactoryBean所创建的Bean,如果我们想获取到这个FactoryB*ean需要在名字前面拼接"&“,行如这种形式:getBean(”&myFactoryBean")

也就是说CommonExternalServiceFactoryBean实现了FactoryBean接口  ,所以当Spring容器查找“MapServiceProxy”这个对象的时候,不会返回CommonExternalServiceFactoryBean类型的实例对象,而是会通过调用getObject()方法返回对象,CommonExternalServiceFactoryBean的getObject方法如下:

public BaseCommonService getObject() throws Exception {
    logger.info("获取代理对象!");
    return (BaseCommonService)this.proxyObj;
}

而BaseCommonService是接口PuDaoService的父接口的父接口,如此便返回一个和PuDaoService父接口的父接口类型的对象,但是还有疑问,从代码角度来讲返回的不是PuDaoService接口的实现类,为什么可以当做PuDaoService接口的实现类?(实际的情况确实是返回PuDaoService父接口,即CommonMapExternalService类型的对象,BaseCommonServic是个空接口)

 

补充:上述疑问经过试验后得知,实现FactoryBean接口的对象返回的是getObjectType里所返回的类型,而此类中

public Class<?> getObjectType() {
return CommonExternalService.class; //返回这个接口有excute方法
}

所以实际上得到的是CommonExternalServicele类型的bean

 

附一个讲的不错的Factorybean的帖子:

https://blog.csdn.net/qq_36963950/article/details/108299757

posted @ 2023-02-14 17:09  龙祭司  阅读(25)  评论(0)    收藏  举报