码迷,mamicode.com
首页 > 其他好文 > 详细

Singleton与Prototype

时间:2020-04-27 13:25:14      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:方式   通过   调度   set   线程   重用   存在   over   意义   

Singleton Bean

对于singleton bean来说,IoC容器只管理一个singleton bean的一个共享实例,所有匹配该bean定义的请求都会让IoC容器返回一个特定的bean实例。

也就是说,当定义一个bean是singleton范围时,IoC容器仅创建一个由该bean定义的对象实例。该单个实例储存在缓存中,对该bean所有后续请求和引用都将返回缓存中的对象实例。

在Spring IoC容器中,singleton bean是默认创建bean的方式,可以更好地重用对象,节省开销。

Prototype Bean

对于prototype bean来说,IoC容器每次处理该bean的请求时都会创建一个新的bean实例。

从某种意义上来说,IoC容器在prototype bean上的作用等同于Java的new操作符,所有实例的生命周期管理都必须由客户端处理。

多线程下的Singleton与Prototype

多线程情况下如果需要每次调用都生成一个实例,可以设置scope为prototype。

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Task implements Runnable { 
    @Override
    public void run() {
    }
}

但是,如果singleton bean依赖prototype bean,通过依赖注入方式,prototype bean在singleton bean实例化时只会创建一次。

@Service
public class TaskService {
    @Autowired
    Task task;

    public void startTask(){
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(task,1000,2000, TimeUnit.MILLISECONDS);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(task,1000,2000, TimeUnit.MILLISECONDS);
    }
}

调度两个线程,实际上只初始化了一个Task实例,这样线程就不安全了。

如果singleton bean想每次都创建一个新的prototype bean的实例,一种方式是方法注入,可以通过实现ApplicationContextAware接口来获取ApplicationContext实例,通过getBean方法来获取到protrotype bean的实例。

@Service
public class TaskService implements ApplicationContextAware {
    @Autowired
    Task task;

    private ApplicationContext applicationContext;

    public void startTask(){
        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2);
        task = applicationContext.getBean("task",Task.class);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(task,1000,2000, TimeUnit.MILLISECONDS);
        task = applicationContext.getBean("task",Task.class);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(task,1000,2000, TimeUnit.MILLISECONDS);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

另一种方式是代理模式,设置@Scope注解的一个代理字段proxyMode,默认是不使用,这里改为使用代理即可。

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Task implements Runnable {
    @Override
    public void run() {
    }
}

 

Singleton与Prototype

标签:方式   通过   调度   set   线程   重用   存在   over   意义   

原文地址:https://www.cnblogs.com/asleaf/p/12785934.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!