前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring温习-FactoryBean应用

spring温习-FactoryBean应用

作者头像
码农戏码
发布2021-03-23 11:21:54
7830
发布2021-03-23 11:21:54
举报
文章被收录于专栏:DDD

不管是平时,还是面试,现在对于spring的讨论少了很多,不再像刚进入人们视野时,那么抢眼;spring现在更像空气一样,只要是java构建的项目,十之八九都是建立在spring之上,因此不可轻视,温故而知新

《BeanFactory与FactoryBean》之后,再看FactoryBean的应用

在上面的文章中指定FactoryBean可以更加灵活的创建Bean,那就从Spring管理Bean方式说起

XML配置Bean

这种方式,是最早的,借助XML,spring创建bean,来分离调用方与被调用方

代码语言:javascript
复制
<bean id="helloWorld" class="me.spring.beans.HelloWorld">
    <property name="name" value="Spring"></property>
</bean>

但是xml不够简洁,且没有编译时检查等功能

@Component @Service

注解开始流行,spring陆续引入了很多注解,关于Bean的有很多

@Component @Service @Repositiory

Java注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的

这些都是把Bean托管给容器

@Bean

从spring3.0开始,可以使用@Configuration与@Bean组合来创建Bean

此注解相对于@Service更灵活了些,如果一个第三方jar中的类需要托管给spring,是没法在类注明@Service注解的,

当然你可以使用XML来实现,但已经约定大于配置,xml不再推荐

除了突破第三方jar限制外,还有

  • 关注点分离,使用@Bean,可以把Bean的创建全部放到了一个地方,接口及其实现不再与具体框架性代码有任何耦合

FactoryBean

虽然@Bean已经相对@Service很灵活了,但还是需要使用@Bean声明,有一些场景无法应对

比如包装RPC,之前写过《RPC的套路》,其实这儿有点AOP的味道

远程service数量是不定的,不能会每一个service去创建并声明上@Bean

一、创建一个FactoryBean

FactroyBean创建的Bean是getObjectType()返回的类型,怎么动态指定此remoteServer,需要使用BeanDefinitionBuilder

代码语言:javascript
复制
@Slf4j
public class RemoteProxyFactoryBean<T> implements FactoryBean<T> , MethodInterceptor {

    @Setter
    @Getter
    private Class<T> remoteService;

    @Setter
    @Getter
    private String url;


    @Override
    public T getObject() throws Exception {
        T service = ProxyFactory.getProxy(remoteService, this);
        return service;
    }

    @Override
    public Class<T> getObjectType() {
        return remoteService;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("RemoteProxyFactoryBean invoke");
        Method method = invocation.getMethod();
        log.info("method:{} invoked",method.getName());

        if (method.getDeclaringClass() == Object.class && method.getName().equals("toString")) { return remoteService.getName() + "@" + System.identityHashCode(remoteService); }

        //远程调用service,可以使用HTTP,也可以是TCP
        StringBuilder sb = new StringBuilder(url);
        sb.append(method.getName());
        sb.append("?var=");
        sb.append(Arrays.toString(invocation.getArguments()));

        log.info("get url:{}",sb.toString());
        return null;
    }
}

二、BeanDefinitionBuilder构建Bean注册spring

使用BeanDefinitionBuilder来构建RemoteProxyFactoryBean的属性,并注册到spring; 注意到上面的RemoteProxyFactoryBean并没有使用@Component托管给spring

代码语言:javascript
复制
private void registeRemoteService() throws IOException {
    SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(this.applicationContext);

    //读取此包下的所有类,进行包装
    Resource[] resources = applicationContext.getResources(resolvePackageToScan("com.jack.remote.service"));

    List<String> classNames = Arrays.stream(resources).map(resource -> {
        MetadataReader metadataReader = null;
        try {
            metadataReader = metadataReaderFactory.getMetadataReader(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return metadataReader.getClassMetadata().getClassName();
    }).collect(Collectors.toList());

    //托管给容器
    classNames.forEach(clazz -> {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(RemoteProxyFactoryBean.class);
        beanDefinitionBuilder.addPropertyValue("remoteService",clazz).addPropertyValue("url","http://remotehost/");

        defaultListableBeanFactory.registerBeanDefinition(clazz+"-proxy",beanDefinitionBuilder.getBeanDefinition());
    });
}

三、装配

对于远程service包下的类,就可以直接使用@Autowired来装配

总结

至此FactoryBean已经完结,对于它的作用已经了解:它是一个能生产或修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农戏码 微信公众号,前往查看

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

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

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