Ioc in Spring Ioc in Spring
IOC (Inversion of Control)
控制反转是一种不同对象之间解耦合的机制. 一般在实际应用中分解为两种Dependency Injection和Dependency Lookup, 两者的实现也不一样. 两者的不同在于在Dependency Lookup中对象持有依赖对象的引用, 而Dependency Injection是由IOC容器负责在适当的时候把依赖对象注入到目标对象中的.
Dependency Lookup
Dependency Lookup一般也分为两种类型: Dependency pull, Contextualized Dependency Lookup.
Dependency Pull
就是把对象都注册到某一个registry上, 一般是一个JNDI Registry(可以认为是一个很大的xml), 在需要的时候容器会在适当的时候通过注册的key取出这个bean, 然后装配.
public class DependencyPull {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext
("META-INF/spring/app-context.xml");
MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}
Contextualized Dependency Lookup
同Dependency Pull不同的是, Contextualized Dependency Lookup是由容器管理的, 不是注册到xml中的, 而是动态地注册到容器中的, 一般容器是由底层应用服务器或者是框架提供的.
例如注册到容器的组件应该实现某个搜索的方法:
public interface ManagedCompenet{
void performLookup(Container container);
}
而容器需要有这样的接口:
public interface Container{
Object getDependency(String key);
}
需要依赖对象时可以如下引用:
public class ContextualizedDependencyLookup implements ManagedComponent {
private Dependency dependency;
@Override
public void performLookup(Container container) {
this.dependency = (Dependency) container.getDependency("myDependency");
}
@Override
public String toString() {
return dependency.toString();
}
}
普通的开发会有生命周期的影响.
而IOC的核心就是生成和销毁都不由引用者本身管理, 而是由第三方管理, 最多的是数据库连接, 使用者不再需要管理数据库连接的生命周期. 如果用的不对, 则会引发异常.
Dependency Injection
也分为两种, Constructor Dependency Injection 和 Setter Dependency Injection.
public class ConstructorInjection {
private Dependency dependency;
public ConstructorInjection(Dependency dependency) {
this.dependency = dependency;
}
@Override
public String toString() {
return dependency.toString();
}
}
public class SetterInjection {
private Dependency dependency;
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
@Override
public String toString() {
return dependency.toString();
}
}
Lookup和Injection两者之间的差别主要在于,对于lookup已经做到了解耦,但是还是需要在目标对象中通过操作或者实现接口得到依赖对象(代码更少,不是), 而Injection更彻底一些.
另一个特殊的好处是, 使用Injection更方便测试, 也可以使得测试和开发分离.