平常的Java开发中,程序员在某个类中需要依赖其它类的方法。

通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理。

Spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过Spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。

依赖注入的另一种说法是"控制反转"。通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员。

而控制反转是指new实例工作不由我们程序员来做而是交给Spring容器来做。

Spring有多种依赖注入的形式,本篇文章仅介绍Spring通过xml进行IOC配置的方式。

1.Set注入

这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringDao的set方法(这是ioc的注入入口):

package com.bless.springdemo.action;
public class SpringAction {
//注入对象springDao
private SpringDao springDao;
//一定要写被注入对象的set方法
public void setSpringDao(SpringDao springDao) {
this.springDao = springDao;
} public void ok(){
springDao.ok();
}
}

随后编写spring的xml文件,<bean>中的name属性是class属性的一个别名,class属性指类的全名,因为在SpringAction中有一个公共属性Springdao,所以要在<bean>标签中创建一个<property>标签指定SpringDao。<property>标签中的name就是SpringAction类中的SpringDao属性名,ref指下面<bean name="springDao"...>,这样其实是spring将SpringDaoImpl对象实例化并且调用SpringAction的setSpringDao方法将SpringDao注入:

<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(1)依赖注入,配置当前类中相应的属性-->
<property name="springDao" ref="springDao"></property>
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>

2.构造器注入

这种方式的注入是指带有参数的构造函数注入,看下面的例子,我创建了两个成员变量SpringDao和User,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在SpringAction的构造函数中注入,也就是说在创建SpringAction对象时要将SpringDao和User两个参数值传进来:

public class SpringAction {
//注入对象springDao
private SpringDao springDao;
private User user; public SpringAction(SpringDao springDao,User user){
this.springDao = springDao;
this.user = user;
System.out.println("构造方法调用springDao和user");
} public void save(){
user.setName("卡卡");
springDao.save(user);
}
}

在XML文件中同样不用<property>的形式,而是使用<constructor-arg>标签,ref属性同样指向其它<bean>标签的name属性:

<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->
<constructor-arg ref="springDao"></constructor-arg>
<constructor-arg ref="user"></constructor-arg>
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
<bean name="user" class="com.bless.springdemo.vo.User"></bean>

解决构造方法参数的不确定性,你可能会遇到构造方法传入的两参数都是同类型的,为了分清哪个该赋对应值,则需要进行一些小处理:
下面是设置index,就是参数位置:

<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<constructor-arg index="0" ref="springDao"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>

另一种是设置参数类型:

<constructor-arg type="java.lang.String" ref=""/>

3.静态工厂的方法注入

静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让spring管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过spring注入的形式获取:

package com.bless.springdemo.factory; 

import com.bless.springdemo.dao.FactoryDao;
import com.bless.springdemo.dao.impl.FactoryDaoImpl;
import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl; public class DaoFactory {
//静态工厂
public static final FactoryDao getStaticFactoryDaoImpl(){
return new StaticFacotryDaoImpl();
}
}

同样看关键类,这里我需要注入一个FactoryDao对象,这里看起来跟第一种注入一模一样,但是看随后的xml会发现有很大差别:

public class SpringAction {
//注入对象
private FactoryDao staticFactoryDao; public void staticFactoryOk(){
staticFactoryDao.saveFactory();
}
//注入对象的set方法
public void setStaticFactoryDao(FactoryDao staticFactoryDao) {
this.staticFactoryDao = staticFactoryDao;
}
}

Spring的IOC配置文件,注意看<bean name="staticFactoryDao">指向的class并不是FactoryDao的实现类,而是指向静态工厂DaoFactory,并且配置 factory-method="getStaticFactoryDaoImpl"指定调用哪个工厂方法:

<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction" >
<!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->
<property name="staticFactoryDao" ref="staticFactoryDao"></property>
</property>
</bean>
<!--(3)此处获取对象的方式是从工厂类中获取静态方法-->
<bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>

4.实例工厂的方法注入

实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法:

public class DaoFactory {
//实例工厂
public FactoryDao getFactoryDaoImpl(){
return new FactoryDaoImpl();
}
}

那么下面这个类没什么说的,跟前面也很相似,但是我们需要通过实例工厂类创建FactoryDao对象:

public class SpringAction {
//注入对象
private FactoryDao factoryDao; public void factoryOk(){
factoryDao.saveFactory();
} public void setFactoryDao(FactoryDao factoryDao) {
this.factoryDao = factoryDao;
}
}

最后看spring配置文件:

<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)-->
<property name="factoryDao" ref="factoryDao"></property>
</bean> <!--(4)此处获取对象的方式是从工厂类中获取实例方法-->
<bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean>
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>

5.总结

Spring IOC注入方式用得最多的是(1)(2)种,多写多练就会非常熟练。

另外注意:通过Spring创建的对象默认是单例,如果需要创建多实例对象可以在<bean>标签后面添加一个属性:

<bean name="..." class="..." scope="prototype">

Spring 依赖注入方式详解的更多相关文章

  1. Spring 依赖注入方式详解(四)

    IoC 简介 平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想 ...

  2. Spring IOC 注入方式详解 附代码

    引言 Spring框架作为优秀的开源框架之一,深受各大Java开发者的追捧,相信对于大家来说并不陌生,Spring之所以这么流行,少不了他的两大核心技术IOC和IOP.我们这里重点讲述Spring框架 ...

  3. SpringDI四种依赖注入方式详解

    文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star!搜索关注微信公众号 [码出Offer] 领取各种学习资料! LOGO SpringDI(依赖注入) 一.DI概述 De ...

  4. Spring事务Transaction配置的五种注入方式详解

    Spring事务Transaction配置的五种注入方式详解 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学 ...

  5. spring IOC注解方式详解

    本文分为三个部分:概述.使用注解进行属性注入.使用注解进行Bean的自动定义. 一,概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以 ...

  6. Unity依赖注入使用详解

    写在前面 构造器注入 Dependency属性注入 InjectionMethod方法注入 非泛型注入 标识键 ContainerControlledLifetimeManager单例 Unity注册 ...

  7. AngularJS开发指南10:AngularJS依赖注入的详解

    依赖注入是一种软件设计模式,用来处理代码的依赖关系. 一般来说有三种方法让函数获得它需要的依赖: 它的依赖是能被创建的,一般用new操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...

  8. .NET Core 中依赖注入框架详解 Autofac

    本文将通过演示一个Console应用程序和一个ASP.NET Core Web应用程序来说明依赖注入框架Autofac是如何使用的 Autofac相比.NET Core原生的注入方式提供了强大的功能, ...

  9. 依赖注入(IOC) 详解

    https://blog.csdn.net/qq_27093465/article/details/52547290 https://blog.csdn.net/qq_27093465/article ...

随机推荐

  1. 数据表格,查询、导出共用一个form表单,实现文件流方式下载

    在开发中遇到问题是这样的: 在维护老的管理系统的过程中,老板说让加导出功能:项目中,查询的筛选条件是用的表单提交的方式写的. 解决方案有两种: 一.用ajax方式导出 var array = $('# ...

  2. python之装饰器

    一.简单装饰器: #定义装饰器函数 def W1(main_func): def outer(): print("before") main_func() print(" ...

  3. Windows搭建python开发环境,python入门到精通[一]

    从大学开始玩python到现在参加工作,已经有5年了,现在的公司是一家.net的公司用到python的比较少,最近公司有新项目需要用到python,领导希望我来跟其他同事training,就有了这篇博 ...

  4. Linux[Fedora]查找文件包含的字段

    find 与 grep组合查找 find . –name '文件类型' | xargs grep –n '查找内容'文件类型可正则表达式通配, [.]表示当前目录下进行查找,也可自由指定目录.比如: ...

  5. python中mysqldb的用法

    1.引入MySQLdb库 import MySQLdb 2.和数据库建立连接 conn=MySQLdb.connect(host="localhost",user="ro ...

  6. iOS UIButton 图片文字上下垂直布局 解决方案

    实现如图所示效果: 这是一个UIButton,需要改变image和title相对位置. 解决如下: //设置文字偏移:向下偏移图片高度+向左偏移图片宽度 (偏移量是根据[图片]大小来的,这点是关键)b ...

  7. SlidingMenu的简单使用

    1.java代码 1.引入slidingmenu的库 * 2.定义activity继承SlidingFragmentActivity * 3.将onCreate方法改为public的 * 4.加载sl ...

  8. Linux安装Mysql rpm

    1.安装时候会提示与已经安装的RPM包有冲突,所以我们先卸载一些RPM包,要卸载哪些呢?我们要卸载的是包含有mariadb关键字的RPM包,执行命令:rpm -qa|grep mariadb来查看一下 ...

  9. ITer的七夕节,你的情人在哪里(2015-08-19)

    自写<一个程序猿的生命周期>连载以来,迎来第一个七夕节,打算写篇文章纪念一下.我主张过中国自己的节日的,也不反对过其他国家的节日,但是要搞清楚其他国家节日的由来,不要把别人的鬼节当成我们的 ...

  10. NOIP2010普及组题解 -SilverN

    三国游戏 题目内容不放了 由于电脑总是会拆掉最大的组合,所以玩家最多只能得到数值第二大的组合 那么找出第二大的组合就行了 #include<iostream> #include<cs ...