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

    科技2026-04-17  2

    原理

    FactoryBean就是Spring容器中,用来专门生成Bean的一种特殊的Bean. 主要是针对配置文件的表达能力有限应运而生的. 在Spring MVC的特殊Scope的Reqesut,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)

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

    Processed: 0.016, SQL: 9