Spring中singleton bean与prototype bean
singleton :定义bean的范围为每个Spring容器一个实例(默认值).prototype :运行bean可以被多次实例化(使用一次就创建一个实例).1.singleton beanIoC容器只管理一个singleton bean的一个共享实例,所有对id或id匹配该bean定义的bean的请求都会导致Spring容器返回一个特定的bean实例.换句话说,当定义一个sing...
singleton :定义bean的范围为每个Spring容器一个实例(默认值).
prototype :运行bean可以被多次实例化(使用一次就创建一个实例).
1.singleton bean
IoC容器只管理一个singleton bean的一个共享实例,所有对id或id匹配该bean定义的bean的请求都会导致Spring容器返回一个特定的bean实例.换句话说,当定义一个singleton bean,Spring IoC容器将会创建一个由该bean\定义的对象实例.该单个实例存储在缓存中,对该bean所有以后请求和引用都将返回这个缓存中的对象实例.可以更好的重用对象,节省了重复创建对象的开销.
2.prototype bean
IoC容器导致每次对该特定的bean请求时创建一个新的bean实例.从某种意义上来说,Spring容器在prototype bean上的作用等同于java的new操作符.
3.陷阱(多线程场景)
以下是一个prototype bean例子
package com.libo.spring.test;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class DadTask implements Runnable {
static Logger logger = Logger.getLogger("DadTask.class");
@Autowired
DadDao dadDao;
private String name;
public DadTask setDadTask(String name) {
this.name = name;
return this;
}
@Override
public void run() {
// TODO Auto-generated method stub
logger.info("DadTask:"+this+";DadDao:" +dadDao+";"+dadDao.sayhello(name));
}
}
如果singleton bean依赖prototype bean,通过依赖注入方式,prototype bean在singleton bean实例化时会创建一次(只一次),看以下例子
package com.libo.spring.test;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private DadTask dadTask;
public void startTask() {
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2);
scheduledThreadPoolExecutor.scheduleAtFixedRate(dadTask.setDadTask("Lily"),1000 , 2000, TimeUnit.MILLISECONDS);
scheduledThreadPoolExecutor.scheduleAtFixedRate(dadTask.setDadTask("Lucy"),1000 , 2000, TimeUnit.MILLISECONDS);
}
}
调度"Lily"和"Lucy"两个线程,实际上只初始化一个实例,以下是解决思路:
如果singleton bean想每次都去创建一个新的Prototype bean的实例,需要通过方法注入的方式.可以通过实现ApplicationContextAware接口来获取AppliationContext实例,继而通过getBean方法来获取到prototype bean的实例,程序修改如下:
package com.libo.spring.test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Service
public class UserServiceu implements ApplicationContextAware{
@Autowired
private DadTask dadTask;
public ApplicationContext applicationContext;
public void startTask() {
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2);
dadTask = applicationContext.getBean("dadTask",DadTask.class);
scheduledThreadPoolExecutor.scheduleAtFixedRate(dadTask.setDadTask("Lily"),1000 , 2000, TimeUnit.MILLISECONDS);
dadTask = applicationContext.getBean("dadTask",DadTask.class);
scheduledThreadPoolExecutor.scheduleAtFixedRate(dadTask.setDadTask("Lucy"),1000 , 2000, TimeUnit.MILLISECONDS);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
this.applicationContext = applicationContext;
}
}
例子摘自:<Spring singleton bean与prototype bean的依赖>
更多推荐
所有评论(0)