接触过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对象的代理类。

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

Spring依赖注入原理的更多相关文章

  1. Spring依赖注入原理分析

    在分析原理之前我们先回顾下依赖注入的概念: 我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念.具体含义是:当某个角色( ...

  2. Spring学习笔记——Spring依赖注入原理分析

    我们知道Spring的依赖注入有四种方式,各自是get/set方法注入.构造器注入.静态工厂方法注入.实例工厂方法注入 以下我们先分析下这几种注入方式 1.get/set方法注入 public cla ...

  3. Spring 依赖注入原理

    所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bean对象,以及销毁它.所以我们只需从容器直接获取Bean对象就行, ...

  4. 形象化的spring 依赖注入原理

      转. IoC就是Inversion of Control,控制反转.在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制.这称为控制反转. 下面我们以几个例子来说明什 ...

  5. spring依赖注入原理剖析

    PropertyDefinition.java package junit.test; public class PropertyDefinition { private String name; p ...

  6. Spring、Spring依赖注入与编码剖析Spring依赖注入的原理

    Spring依赖注入 新建PersonIDao 和PersonDao底实现Save方法: public interface PersonIDao { public void save(); } pub ...

  7. Spring 源码分析之 bean 依赖注入原理(注入属性)

         最近在研究Spring bean 生命周期相关知识点以及源码,所以打算写一篇 Spring bean生命周期相关的文章,但是整理过程中发现涉及的点太多而且又很复杂,很难在一篇文章中把Spri ...

  8. (转)编码剖析Spring依赖注入的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...

  9. Spring依赖注入:@Autowired,@Resource和@Inject区别与实现原理

    一.spring依赖注入使用方式 @Autowired是spring框架提供的实现依赖注入的注解,主要支持在set方法,field,构造函数中完成bean注入,注入方式为通过类型查找bean,即byT ...

随机推荐

  1. 阿里云全民云计算活动:云服务器ECS二折起(云主机)采购指南

    首先要注册并登录阿里云,完成实名认证 可以用手机号新注册账号, 也可以使用淘宝账号直接登录,其他的登录方式还支持微博账号和支付宝账号等. 登录后如下图,先点"控制台", 然后鼠标移 ...

  2. 【Kafka源码】KafkaConsumer

    [TOC] KafkaConsumer是从kafka集群消费消息的客户端.这是kafka的高级消费者,而SimpleConsumer是kafka的低级消费者.何为高级?何为低级? 我们所谓的高级,就是 ...

  3. C#实现DirectShow技术开发准备

    DirectShow组件在“C:\WINDOWS\system32”目录下的Quartz.dll动态库中,要使C#代码引用COM对象和接口,必须将COM类型库转换为.NET框架元数据,从而有效地创建一 ...

  4. Katana-CookieAuthenticationMiddleware-源码浅析

    准备工作 第一步,建立一个模板项目 本文从CookieAuthenticationMiddleware入手分析,首先我们来看看哪里用到了这个中间件,打开VisualStudio,创建一个Mvc项目,然 ...

  5. Android隐藏软键盘

    1,用java代码隐藏: /**隐藏软键盘**/        View view = getWindow().peekDecorView();        if (view != null) { ...

  6. Android设置屏幕方向

    设置方法:在AndroidManifest.xml中的Activity里加一个属性android:screenOrientation.例如设置该Activity为横向 <activity and ...

  7. JAVA构造函数简析

    构造函数是java新建对象的一种手段 构造函数可以重载 如果一个类中有多个域,那么就可能需要多个构造函数.这时候,使用重载就可以了 构造函数中this和super的使用 this:(1)this用于本 ...

  8. re部分

    0x01.Writeup-RE-CM_2 题目: 解题思路: 1.这个是经过xor的,王老师提示说用xortool,于是放进kali,装好之后执行 xortool CM_2.exe -b, 0.out ...

  9. web-php绕过

    0x01.web-PHP的悖论1 题目: 链接:http://game.sycsec.com:2009/10111.php 解题思路: 1.首先,web对于选择二进制方向的我这个菜鸡绝对是十分懵逼的, ...

  10. opengl启动过程

    GLuint _program = glCreateProgram(); //create shader program GLuint vertShader, fragShader;//顶点着色器,片 ...