前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我猜你不知道FactoryBean是什么东西

我猜你不知道FactoryBean是什么东西

作者头像
DH镔
发布2019-12-20 17:02:54
5110
发布2019-12-20 17:02:54
举报

先说重点

BeanFactory

BeanFactory定义了IOC容器的最基本形式,并提供了IOC容器应遵守的的最基本的接口,也就是Spring IOC所遵守的最底层和最基本的编程规范。在Spring代码中,BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactoryXmlBeanFactoryApplicationContext等,都是附加了某种功能的实现。BeanFactory不是这文的重点。

FactoryBean

先看名字,根据经验猜测这是一个Bean。事实它的确是一个Bean,作用用一句话描述的话,就是一个生成Bean的工厂Bean。一般情况下,在Spring中可以使用注解xmlJavaConfig的方式配置产生bean加入到ioc的容器中,但是在某些情况下,实例化bean的过程复杂或者需要更加灵活的配置的时候,就可以考虑 FactoryBean 这个工厂接口来实例化bean。例如mybatis-spring中的SqlSessionFactoryBean

先看下接口

代码语言:javascript
复制
public interface FactoryBean<T> {
    T getObject() throws Exception;
    Class<?> getObjectType();
    default boolean isSingleton() {
        return true;
    }
}

getObject

返回由FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中

getObjectType

返回需创建Bean的类型,这方法在使用泛型的时候可以不重写,直接返回null,但是在创建prototype的bean的时候这里最好返回Bean的类型。还有一点是,如果不是使用泛型,getObjectType也不返回对象类型,使用Autowired将无法注入对象。

isSingleton

是否单例

实战

哈哈,这也是我写这笔记的原因。一直都知道FactoryBean的存在,但没有找到适合的应用场景,今天给我遇到了。需求是这样的

请求esb提供的接口获取数据,esb实现的方式是 webservice 。报文是又长又臭的xml,都写在类的话,对于强迫症的我是接受不了的,所有想到了下面这个方法

报文写在xml中,定义FactoryBean在实例化的过程中读取xml,通过动态代理映射到接口的方法中。仅文字有点抽象,我们看代码

1.定义接口

代码语言:javascript
复制
public interface EsbService {

    String func019(String phoneNumber);
    
    String func155(String customerId);
}

上面这个类定义了两个接口,func019和func155对应esb系统中的两个接口,把对应的请求报文放在resources目录中,像下面这个样子,一一对应方法名称

代码语言:javascript
复制
|resources
|---esb
|-----func019.xml
|-----fubc155.xml

2.定义FactoryBean

getObject中使用了JDK动态代理创建EsbService,目的就是像mybatis的Mapper一样,仅需定义接口和xml就可以实现方法。

代码语言:javascript
复制
@Component
public class EsbServiceFactoryBean implements FactoryBean<EsbService> {


    @Override
    public EsbService getObject() throws Exception {
        return (EsbService) Proxy.newProxyInstance(getClass().getClassLoader(),
                new Class[]{EsbService.class},
                new EsbServiceProxy("esb"));
    }

    @Override
    public Class<?> getObjectType() {
        return EsbService.class;
    }


}

3.动态代理的逻辑

代码语言:javascript
复制
public class EsbServiceProxy implements InvocationHandler {

    /**
     * xml文件后缀
     */
    private static final String XML_FILE_SUFFIX = ".xml";

    /**
     * esb接口请求地址
     */
    private static final String ESB_URL = "";

    /**
     * 缓存xml
     */
    private Map<String, String> cacheXml = new ConcurrentHashMap<>();

    public EsbServiceProxy(String path) throws Exception {
        // 读取报文到cacheXml中
        File folder = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + path);
        File[] esbXmlFiles = folder.listFiles();
        if (esbXmlFiles != null) {
            for (File esbXmlFile : esbXmlFiles) {
                String fileName = esbXmlFile.getName().replace(XML_FILE_SUFFIX, "");
                String xml = FileUtil.readString(esbXmlFile, StandardCharsets.UTF_8);
                cacheXml.put(fileName, xml);
            }
        }
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        String xml = cacheXml.get(methodName);
        xml = StrUtil.format(xml, args);
        return HttpUtil.createPost(ESB_URL)
                .header("Content-type", "text/xml")
                .header("SOAPAction", "call")
                .body(xml)
                .execute()
                .body();
    }

}

over,收工。以后需要添加其它api接口的只要把报文往文件夹一放,定义接口签名就可以了。

总结

大概的流程是:读取xml -> 缓存到map -> 方法签名与xml映射 -> 动态代理实现 -> 注入容器

有时候总觉得学的很多东西没有用处,大概就是对该知识点了解得不够深入,再需要的时候没有想出来。除了FactoryBean,还有Spring中的BeanDefinitionRegistryPostProcessor可以了解下

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 先说重点
  • BeanFactory
  • FactoryBean
    • getObject
      • getObjectType
      • 实战
      • 总结
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档