IOC(Inversion of Control, 控制反转)
IOC还有个别名叫依赖注入(DI,Dependency Injection)
作用:一个类中的依赖类不需要自己去new,由IOC容器负责创建和管理。
一.在IOC出现之前
FXNewsProvider类需要先实例化俩个依赖类(IFXNewsListener、IFXNewsPersister),才能调用getAndPersisterNews方法。以前就是在类的构造函数实例化。,假如,使用Dow Jones的新闻,提供相应的DowJonesNewsListener和DowJonesNewsPersister两个实现,如下:
public class FXNewsProvider{
private IFXNewsListener newsListener;
private IFXNewsPersister newPersister;
//Ioc出现前,依赖类是自己创建和管理
public FXNewsProvider(){
newsListener = new DowJonesNewsListener();
newPersister = new DowJonesNewsPersister();
}
public void getAndPersistertNews(){
String[] newsIds = newListener.getAvailableNewsIds();
if(ArrayUtils.isEmpty(newsIds){
return;
}
for(String newsId:newsIds){
FXNewsBean newsBean = newsListener.getNewsByPK(newsId);
newPersistener.persistNews(newsBean);
newsListener.postProceeIfNexessary(newsId);
}
}
}
二、构造方法注入
被注入对象可以通过其构造方法中声明依赖对象的参数列表
public FXNewsProvider(IFXNewsListener newsListener, IFXNewsPersister newsPersister){
this.newsListener = newsListener;
this.newPersister = newsPersister;
}
三、setter方法注入
对于JavaBean对象来说,通过setXXX()和getXXX()方法访问属性,这些方法统称为setter方法,当前对象只要为其依赖对象所对应的属性添加setter方法,就可以将相应的依赖对象设置都被注入对象中
public class FXNewsProvider{
private IFXNewsListener newsListener;
private IFXNewsPersister newPersister;
public IFXNewsListener getNewsListener(){
return newsListener;
}
public void setNewsListener(IFXNewsListener newsListener){
this.newsListener = newsListener;
}
public IFXNewsPersister getNewsPersister(){
return newsPersister;
}
public void setNewsPersister(IFXNewsPersister newsPersister){
this.newsPersister = newsPersister;
}
}
四、接口注入(不常用)
五、基于注解的依赖注入(重点)
5.1自动绑定(@ Autowired)按照类型进行匹配
@Autowired可以让容器知道需要为当前类注入那些依赖。(无论是private、protected还是public)
public class FXNewsProwider{
@Autowired
private IFXNewsListner newsListener;
@Autowired
private IFXNewsPersister newPersistener;
...
}
过程:仅仅将@Autowired标注于类定义,并不能让Spring的IOC容器聪明到完成依赖的注入。这需要容器配置文件告诉容器该去哪里找到对应的依赖并完成注入。
为了给容器定义的每个bean定义的实例注入依赖,通过遍历它们,然后通过反射,检查每个bean定义对应的类上各种可能位置上的@Autowired,如果有,就从当前的容器管理的对象获取到对应的对象,设置给被@Autowired所标注的。蓝色文字描述的过程,由Spring的IoC容器使用BeanPostProcessor自定义实现,无需我们自己实现如:
<beans>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="newsProvider" class ="..FXNewsProvider"/>
<bean id="djNewsListener" class="..DowJonesNewListerner"/>
<bean id="djNewsPersister" class="..DowJonesNewsPersister"/>
</beans>
5.2@ Qualifier 按照名称匹配
当前@Autowired标注的依赖在容器中只能找到一个实例与之对应,但是要是出现两个或者多个同一类型的对象实例,就无法解决,而@Qualifier为此而生。
<beans>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="newsProvider" class ="..FXNewsProvider"/>
<bean id="djNewsListener" class="..DowJonesNewListerner"/>
<bean id="reutersNewsListner" class="..RetersNewsListenr"/>
<bean id="djNewsPersister" class="..DowJonesNewsPersister"/>
</beans>
public class FXNewsProwider{
@Autowired
@Qualifier("reutersNewsListner")
private IFXNewsListner newsListener;
@Autowired
private IFXNewsPersister newPersistener;
...
}
也可以标注于方法参数之上
public class FXNewsProvider{
...
@Autowired
public void setUp(@Qualifier("retuerNewsListner") IFXNewsListener newsListener){
this.newsListener = newsListener;
}
}