原理
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
;
@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();
context
.registerBean(SingletonOnOddFactoryBean
.class);
context
.refresh();
final Man man
= context
.getBean("singletonOnOddFactoryBean", Man
.class);
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
)
从结果可以看到奇数线程返回的都是同一个随机数,而偶数线程返回的都是不同对象.