当注入的是接口,再由调用者注入具体接口实现类时就提高了扩展性。
在spring中,依赖注入有以下几种方式:
普通的java程序也可以通过这几种方式注入,那么什么时候用什么依赖注入方式合适? 这要从下面几个方面考虑:
通过属性注入,注入的类在类定义时已经固定写死,不可改变;而通过构造器注入和方法注入,则可以由调用者在调用时传入,增加了可扩展性。
通过属性注入和构造器注入,意味着注入类的生命周期和宿主类的生命周期一样,只要宿主类存在注入类就存在,也就是说这段时间注入类会一直占用内存;而通过方法注入,意味着一般情况下注入类仅在此方法内使用,方法结束,注入类的生命周期就结束,占用内存得以释放。
根据以上这两点,我们就可以很容易判断何时应该使用哪种方式注入。
下面,我们通过java的JUC包下的ThreadPoolExecutor类来看依赖注入是如何提高扩展性的。
其中绿色部分都是接口,可由调用者提供具体实现并注入,这样就极大的提高了扩展性。各个接口职责说明如下:
类 | 职责 |
---|---|
ThreadPoolExecutor | 线程执行器 |
BlockingQueue | 线程池所使用的缓冲队列,队列长度决定了能够缓冲的最大工作线程数量 |
Runnable | 线程队列中的Runnable |
ThreadFactory | 创建工作线程的线程工厂 |
RejectedExecutionHandler | 线程执行器中线程队列满时增加新线程的处理策略接口 |
DiscardOldestPolicy | 抛弃线程队列中最老的未执行工作线程,添加新的工作线程。 |
CallerRunsPolicy | 重复执行,直到成功,在closeConnectionExecutor中使用。 |
AbortPolicy | 抛弃超出线程队列负载的工作线程,并抛出异常。 |
DiscardPolicy | 忽略超出线程队列复杂的工作线程,不做任何处理。 |
各接口的注入方式为构造器注入:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { 复制代码