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

原理

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)

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

猜你喜欢

转载自blog.csdn.net/weixin_46080554/article/details/108970460