基于Spring的FactoryBean接口,根据不同线程id返回不同对象

5 篇文章 0 订阅
4 篇文章 0 订阅

原理

FactoryBean就是Spring容器中,用来专门生成Bean的一种特殊的Bean.
主要是针对配置文件的表达能力有限应运而生的.
在Spring MVC的特殊ScopeReqesut,Session就是通过实现FactoryBean从而达到每个请求生成的都是不同的对象.
内部就是通过将对象与线程绑定,如果该线程已有实例则直接返回,不然就生成一个新对象.

例子

import lombok.Data;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Data
public class SingletonOnOddFactoryBean implements FactoryBean {

    @Data
    public static class Man {
        private long randId = new Random().nextLong();
    }

    private Man man;

    /**
     * 根据线程id,如果是奇数返回同一个对象,如果是偶数返回不同的对象
     *
     * @return
     * @throws Exception
     */
    @Override
    public Object getObject() throws Exception {
        final long id = Thread.currentThread().getId();
        if (id % 2 == 1) {
            if (null == man) {
                synchronized (this) {
                    if (null == man) {
                        man = new Man();
                    }
                }
            }
            return man;
        } else {
            return new Man();
        }
    }

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

    @Override
    public boolean isSingleton() {
        return false;
    }

    public static void main(String[] args) {

        final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册bean
        context.registerBean(SingletonOnOddFactoryBean.class);

        context.refresh();

        final Man man = context.getBean("singletonOnOddFactoryBean", Man.class);
        // `&`表示获取bean的工厂,而不是其所生成的bean
        final SingletonOnOddFactoryBean bean = context.getBean("&singletonOnOddFactoryBean", SingletonOnOddFactoryBean.class);

        System.out.println(man);
        System.out.println(bean);

        final int num = 5;
        final ExecutorService executorService = Executors.newFixedThreadPool(num);
        for (int i = 0; i < num; i++) {
            executorService.submit(() -> {
                final Man bean1 = context.getBean("singletonOnOddFactoryBean", Man.class);
                System.out.println(String.format("threadId-%d, %s", Thread.currentThread().getId(), bean1.toString()));
            });
        }

        executorService.shutdown();
        try {
            executorService.awaitTermination(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
SingletonOnOddFactoryBean.Man(randId=-5212458004770305624)
SingletonOnOddFactoryBean(man=SingletonOnOddFactoryBean.Man(randId=-5212458004770305624))
threadId-13, SingletonOnOddFactoryBean.Man(randId=-5212458004770305624)
threadId-14, SingletonOnOddFactoryBean.Man(randId=8775694695084697093)
threadId-15, SingletonOnOddFactoryBean.Man(randId=-5212458004770305624)
threadId-16, SingletonOnOddFactoryBean.Man(randId=-8070015379535590919)
threadId-12, SingletonOnOddFactoryBean.Man(randId=1754824379690885040)

从结果可以看到奇数线程返回的都是同一个随机数,而偶数线程返回的都是不同对象.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕咕咕zhou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值