接触过spring 的同学应该都知道依赖注入,依赖注入又称控制反转,其内涵就是,将创建某个bean的控制权力,由原来需要引用这个bean的bean转移(反转)到外部的spring IOC容器,由IOC容器统一创建,并且注入到需要引用的bean中去。 那么spring是怎么做到依赖注入的,我们来看看spring是怎么做的吧!

其实,spring的本质是一个工厂(beanFactory)或者说bean容器,它按照我们的要求,生产我们需要的各种各样的bean,提供给我们使用。只是在生产bean的过程中,需要解决bean之间的依赖问题,才引入了依赖注入(DI)这种技术。也就是说依赖注入是beanFactory生产bean时为了解决bean之间的依赖的一种技术而已。但是,我们一般都不直接用BeanFactory,而是用它的实现类ApplicationContext,这个类会自动解析我们配置的applicationContext.xml,然后根据我们配置的bean来new对象,将new好的对象放进一个Map中,键就是我们bean的id,值就是new的对象。

我们来看一下beanFactory的代码:

 package org.springframework.beans.factory;

 public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&"; Object getBean(String var1) throws BeansException; <T> T getBean(String var1, Class<T> var2) throws BeansException; <T> T getBean(Class<T> var1) throws BeansException; Object getBean(String var1, Object... var2) throws BeansException; <T> T getBean(Class<T> var1, Object... var2) throws BeansException; ...
}

beanFactory是一个接口,其中定义了各种getBean()方法,我们可以看到返回的是一个object对象,因此通过上下文对象ApplicationContext对象拿到的对象都必须通过强转能变成指定的类型的对象。

我们再来模拟ClassPathXmlApplicationContext的是怎么拿到bean的:

 package com.spring.Context;

 import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; public class ClassPathXmlApplicationContext implements BeanFactory {
private Map<String, Object> beanMap = new HashMap<String, Object>(); //map的value是object
public ClassPathXmlApplicationContext(String fileName) throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(this.getClass().getClassLoader().getResourceAsStream(fileName)); //SAX解析对应的xml配置文件
List<Element> elements = document.selectNodes("/beans/bean");
for (Element e : elements) {
String id = e.attributeValue("id");
String value = e.attributeValue("class");
Object o = Class.forName(value).newInstance(); //利用反射通过类名拿到的类的一个实例对象
beanMap.put(id, o);
}
} public Object getBean(String id) {
return beanMap.get(id);
} }

我们可以发现,通过spring  getBean()拿到的对象实例,都是通过读取applicationContext.xml文件,再通过反射拿到的类的实例对象。

因此,spring注入的对象必须可以实例化,也就是说,接口和抽象类是不能通过spring实现注入的,因为两者都不能实例化。

这就让人很不能理解了,因为在做spring-mybatis整合的时候,我们有一个常见的做法就是在service层通过注解注入dao层接口,在这里不是可以注入接口吗?为什么又说spring不能注入接口呢?

其实,这里注入的接口,并不是真正的接口,我们不妨吧这个注入的“接口”打印出来看看,到底是个什么东西:

 the dao is:  org.apache.ibatis.binding.MapperProxy@33e4ae3b
the dao class is : class com.sun.proxy.$Proxy21

输出显示,其实注入的并不是接口,而是mybatis中的mapper对象的代理类。

至于这个里面的玄机,还是等下次去探讨吧!

最新文章

  1. 三种上传文件不刷新页面的方法讨论:iframe/FormData/FileReader
  2. gitignore 规范
  3. Windows Phone 十四、磁贴通知
  4. React Native的组件ListView
  5. 浅谈new operator、operator new和placement new 分类: C/C++ 2015-05-05 00:19 41人阅读 评论(0) 收藏
  6. zabbix安装排错过程
  7. HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)
  8. Tomcat 服务器服务的注册修改删除
  9. java多线程模拟停车系统
  10. C#缩放和裁剪图片
  11. 【原】Infragistics.Win.UltraWinGrid.UltraGrid 增加行号
  12. Vim的tag系统
  13. Android(java)学习笔记154:使用GridView以及重写BaseAdapter
  14. c# mongo 返回指定的列
  15. spring bean范围
  16. Eclipse 中 Java 项目中 .settings 文件夹作用
  17. java基础(五章)
  18. 暑假练习赛 004 E Joint Stacks(优先队列模拟)
  19. arduino 522样本中文注释
  20. 【Selenium2】【项目实战】

热门文章

  1. MUI框架开发HTML5手机APP(一)--搭建第一个手机APP
  2. linux操作系统基础篇(四)
  3. 查看oracle数据库里哪些语句耗时最长或者效率最低
  4. C#版本websocket及时通信协议实现
  5. hibernate:There is a cycle in the hierarchy! 造成死循环解决办法
  6. jquery总结(来自于一个讲师的总结)
  7. 一位有着工匠精神的博主写的关于IEnumerable接口的详细解析
  8. day01_HTML
  9. 2735:八进制到十进制-poj
  10. Windows系统重装