原理
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)
从结果可以看到奇数线程返回的都是同一个随机数,而偶数线程返回的都是不同对象.