如何使用spring构造注入的优点入

将HelloWorld实例改为构造注入方式实现
Spring支持Set注入(setter injection)和构造注入(constructor injection),但更推荐使用Set注入。上面讲过,第2章的第一个实现HelloWorld的实例就是采用Set注入方式实现的,读者可以参看第 2章的实例。下面笔者把这个实例改为采用构造注入方式实现。改写思路是:首先修改类HelloWorld,在该类中增加一个构造方法,然后修改 Spring的配置文档config.xml,最后编写测试程序TestHelloWorld.java。
修改HelloWorld.java
修改com.gc.action包下的HelloWorld.java,增加一个构造方法,并把要注入的字符串msg作为参数,代码如下,在HelloWorld类中增加了一个构造方法public HelloWorld (String msg)。
//*******HelloWorld.java**************
package com.gc.
public class HelloWorld {
//该变量用来存储字符串
public String msg =
//增加了一个构造方法
public HelloWorld (String msg) {
this.msg =
//设定变量msg的set方法
public void setMsg(String msg) {
this.msg =
//获取变量msg的get方法
public String getMsg() {
return this.
修改config.xml
在Spring中,利用Set注入和构造注入时,在XML配置文档中使用的语法是不一样的。修改配置文件config.xml内容如下:
&?xml version="1.0" encoding="UTF-8"?&
&!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"&
&!--定义一个Bean,通过构造函数进行注入--&
&bean id="HelloWorld" class="com.gc.action.HelloWorld"&
&!--通过构造函数进行注入--&
&constructor-arg index="0"&
&value&HelloWorld&/value&
&/constructor-arg&
代码说明:
constructor-arg,用来表示是通过构造方式来注入参数的。
index="0",表示是构造方法中的第一个参数,如果只有一个参数,则可以不用设置这个属性值。
编写测试程序TestHelloWorld.java
修改TestHelloWorld.java,代码如下:
//******* TestHelloWorld.java**************
package com.gc.
import org.springframework.context.ApplicationC
import org.springframework.context.support.FileSystemXmlApplicationC
import com.gc.action.HelloW
public class TestHelloWorld {
public static void main(String[ ] args) {
//通过ApplicationContext来获取Spring的配置文件
ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");
HelloWorld HelloWorld = (HelloWorld) actx.getBean("HelloWorld");
System.out.println(HelloWorld.getMsg());
运行测试程序并查看输出结果
在Eclipse中运行Java程序的步骤如下:
(1)确保当前在Eclipse中编辑的是TestHelloWorld.java文件。
(2)选择Run→Run As→Java Application命令,Eclipse即可运行TestHelloWorld.java。
(3)输出结果为“HelloWorld”,如图3.1所示。
输出结果为“HelloWorld”
futurehuhu
浏览: 22451 次
来自: shanghai
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'详解Spring 两种注入的方式(Set和构造)实例
作者:passport_daizi
字体:[ ] 类型:转载 时间:
本篇文章主要介绍了Spring 两种注入的方式(Set和构造)实例,Spring框架主要提供了Set注入和构造注入两种依赖注入方式。有兴趣的可以了解一下。
依赖注入是指对象之间关系的控制权由应用代码中转到外部容器。Spring框架主要提供了Set注入和构造注入两种依赖注入方式。
1:Set注入指的就是在接受注入的类中定义一个要被注入的类型的一个set方法,并在参数中定义需要注入的元素。Set注入式一种装配Bean属性的直接方法,但Set注入的一个缺点就是它假设了所有的可变属性都可以通过set方法访问到,无法清晰地表示哪些属性是必须的,哪些属性是可选的。
2:构造注入是在接收注入的类中定义一个构造方法,并在构造方法中定义需要注入的参数。构造注入方式的优势是通过构造方法来强制依赖关系。
下面介绍一下两种方式的用法:
一:在Myeclipse中(笔者使用的是Myeclipse10版本)新建一个项目(Java project或者web project都可)
二:右键项目 - MyEclipse - Add Spring Capabilities(添加Spring支持),选择3.0版本并添加引用核心类库,点击下一步。
三:选择新创建一个spring bean 配置文件放到项目src目录下。
四:点击下一步,指定hibernate 配置页,直接默认,点击完成即可。
五:新建类 HelloWorld.Java
package com.xiami.
public class HelloWorld {
* 默认构造方法
public HelloWorld() {
* 用来进行构造注入的构造方法
* @param str
public HelloWorld(String str) {
this.str =
* 用来进行Set注入的方法
* @param str
public void setStr(String str) {
this.str =
* 输出字符串的方法
public void sayHello() {
System.out.println(str);
六:新建测试类Test.java
package com.xiami.
import org.springframework.beans.factory.BeanF
import org.springframework.beans.factory.xml.XmlBeanF
import org.springframework.core.io.ClassPathR
public class Test {
* @param args
public static void main(String[] args) {
// TODO Auto-generated method stub
//载入spring配置文件
BeanFactory bFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
HelloWorld helloWorld = (HelloWorld) bFactory.getBean("helloService");
helloWorld.sayHello();
七:打开applicationContext.xml文件,进行添加bean配置
以下是两种方式添加bean:
1:采用Set注入方式的Bean类的配置
右击applicationContext.xml的编辑界面 - Spring - new bean 打开Bean向导窗口,填写Bean Id(自定义命名和Test.java中getBean("???")对应。Bean class 选择要注入的HelloWorld类。点击Properties属性选项卡,给该bean新建一个属性。
八:在属性向导窗口填写 Name 对应HelloWorld.java中的属性名称,Spring Type 选择value,type选择String,Value 随便填值。finish 既可。
九:保存applicationContext.xml, 添加bean后,配置文件多了红色标记的部分,读者可以运行Test.java。测试一下。发现hello world字符串已经注入到了str变量上。
&?xml version="1.0" encoding="UTF-8"?&
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"&
&!-- 使用Set方式注入 --&
&span style="color:#ff0000;"&&bean id="helloService" class="com.xiami.spring.HelloWorld"
abstract="false" lazy-init="default" autowire="default"&
&property name="str"&
&value type="java.lang.String"&hello world&/value&
&/property&
&/bean&&/span&
&!-- 使用构造方法方式注入
&bean id="helloService" class="com.xiami.spring.HelloWorld"
abstract="false" lazy-init="default" autowire="default"&
&constructor-arg&
&value type="java.lang.String"&构造方法注入方式&/value&
&/constructor-arg&
2:采用构造注入方式的Bean类的配置
在以上Set方式的Bean Wizard(Bean 向导)窗口,不选择Properties选项卡,变为Constructor Args选项卡。并Add 新增一个构造参数。Index和Java Class 不用填写。
十:在增加构造方式bean的时候,之前第一个得先注释或者删除,不允许有多个id相同的bean。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具博客分类:
注入的方法有很多,通过beans.xml配置属性注入,用构造函数注入,用注释注入,下面介绍怎么用构造函数注入。
参考上一篇博文:
1、给UserServer添加构造方法
public class UserService {
private UserDAO userDAO;
public void add(User user) {
userDAO.save(user);
public UserDAO getUserDAO() {
return userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
public UserService(UserDAO userDAO) {
this.userDAO = userDAO;
}
2、把beans.xml修改为
&?xml version="1.0" encoding="UTF-8"?&
&beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"&
&bean id="u" class="com.jt.dao.impl.UserDAOImpl"&
&bean id="userService" class="com.jt.service.UserService"&
&constructor-arg&
&ref bean="u"/&
&/constructor-arg&
&/beans&
这样就完成了通过构造方法的注入
浏览: 3889 次
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'webapi中如何使用依赖注入
作者:神牛步行3
字体:[ ] 类型:转载 时间:
本篇将要和大家分享的是webapi中如何使用依赖注入,依赖注入这个东西在接口中常用,实际工作中也用的比较频繁,因此这里分享两种在api中依赖注入的方式Ninject和Unity。下面跟着小编一起来看下吧
本篇将要和大家分享的是webapi中如何使用依赖注入,依赖注入这个东西在接口中常用,实际工作中也用的比较频繁,因此这里分享两种在api中依赖注入的方式Ninject和Unity;由于快过年这段时间打算了解下vue.js,所以后面对webapi的分享文章可能会慢点更新,希望支持的朋友们多多谅解,毕竟只有不断充电学习,才能更好的适应it行业吧;本章内容希望大家喜欢,也希望各位多多扫码支持和推荐谢谢:
& Task并行任务抓取博客园首页信息
& IOC框架Ninject的使用
& IOC框架Unity的使用
下面一步一个脚印的来分享:
& Task并行任务抓取博客园首页信息
首先,咋们需要创建一个博客信息实体类 MoBlog ,实体类代码如下:
public class MoBlog
public MoBlog() { }
/// &summary&
/// 作者昵称
/// &/summary&
public string NickName { }
/// &summary&
/// &/summary&
public string Title { }
/// &summary&
///该篇文字地址
/// &/summary&
public string Url { }
/// &summary&
/// &/summary&
public string Des { }
/// &summary&
/// 头像图片地址
/// &/summary&
public string HeadUrl { }
/// &summary&
/// 博客地址
/// &/summary&
public string BlogUrl { }
/// &summary&
/// 点赞次数
/// &/summary&
public int ZanNum { }
/// &summary&
/// 阅读次数
/// &/summary&
public int ReadNum { }
/// &summary&
/// 评论次数
/// &/summary&
public int CommiteNum { }
/// &summary&
/// 创建时间
/// &/summary&
public DateTime CreateTime { }
然后,需要创建一个接口 IBlogsReposity ,并且定义一个如下代码的方法:
public interface IBlogsReposity
/// &summary&
/// 获取博客信息
/// &/summary&
/// &param name="nTask"&&/param&
/// &returns&&/returns&
Task&IEnumerable&MoBlog&& GetBlogs(int nTask);
注意这里定义的返回类型是Task&T&,主要作用是async异步返回博客信息,并且方便使用并行方式抓取不同页数的数据,因此这里传递了一个int类型的参数nTask(表示任务数量);好了咋们来一起看下具体实现接口的 BoKeYuan 类里面的代码:
public class BoKeYuan : IBlogsReposity
public async Task&IEnumerable&MoBlog&& GetBlogs(int nTask)
var blogs = new List&MoBlog&();
//开启nTask个任务,读取前nTask页信息
Task&IEnumerable&MoBlog&&[] tasks = new Task&IEnumerable&MoBlog&&[nTask];
for (int i = 1; i &= tasks.L i++)
tasks[i - 1] = await Task.Factory.StartNew&Task&IEnumerable&MoBlog&&&((page) =&
return GetBlogsByPage(Convert.ToInt32(page));
Task.WaitAll(tasks, TimeSpan.FromSeconds(30));
foreach (var item in tasks.Where(b =& b.IsCompleted))
blogs.AddRange(item.Result);
catch (Exception ex)
return blogs.OrderByDescending(b =& b.CreateTime);
/// &summary&
/// &/summary&
/// &param name="nPage"&页数&/param&
/// &returns&&/returns&
async Task&IEnumerable&MoBlog&& GetBlogsByPage(int nPage)
var blogs = new List&MoBlog&();
var strBlogs = string.E
using (HttpClient client = new HttpClient())
strBlogs = await client.GetStringAsync("/sitehome/p/" + nPage);
if (string.IsNullOrWhiteSpace(strBlogs)) { }
var matches = Regex.Matches(strBlogs, "diggnum\"[^&]+&(?&hzan&\\d+)[^:]+(?&burl&http[^\"]+)[^&]+&(?&title&[^&]+)&\\/a&[^=]+=[^=]+=\"(?&hurl&http://(\\w|\\.|\\/)+)[^&]+&[^\\/]+\\/\\/(?&hphoto&[^\"]+)[^&]+&\\/a&(?&bdes&[^&]+)[^\"]+[^=]+=[^&]+&(?&hname&[^&]+)[^2]+(?&bcreatetime&[^&]+)[^\\(]+\\((?&bcomment&\\d+)[^\\(]+\\((?&bread&\\d+)");
if (matches.Count &= 0) { }
foreach (Match item in matches)
blogs.Add(new MoBlog
Title = item.Groups["title"].Value.Trim(),
NickName = item.Groups["hname"].Value.Trim(),
Des = item.Groups["bdes"].Value.Trim(),
ZanNum = Convert.ToInt32(item.Groups["hzan"].Value.Trim()),
ReadNum = Convert.ToInt32(item.Groups["bread"].Value.Trim()),
CommiteNum = Convert.ToInt32(item.Groups["bcomment"].Value.Trim()),
CreateTime = Convert.ToDateTime(item.Groups["bcreatetime"].Value.Trim()),
HeadUrl = "http://" + item.Groups["hphoto"].Value.Trim(),
BlogUrl = item.Groups["hurl"].Value.Trim(),
Url = item.Groups["burl"].Value.Trim(),
catch (Exception ex)
代码分析:
1. Task&IEnumerable&MoBlog&&[] tasks = new Task&IEnumerable&MoBlog&&[nTask]作为并行任务的容器;
2. Task.Factory.StartNew创建对应的任务
3. Task.WaitAll(tasks, TimeSpan.FromSeconds(30));等待容器里面任务完成30秒后超时
4. 最后通过把item.Result任务结果添加到集合中,返回我们需要的数据
这里解析博客内容信息用的正则表达式,这种方式在抓取一定内容上很方便;群里面有些朋友对正则有点反感,刚接触的时候觉得挺不好写的,所以一般都采用更复杂或者其他的解析方式来获取想要的内容,这里提出来主要是和这些朋友分享下正则获取数据是多么方便,很有必要学习下并且掌握常规的用法,这也是一种苦尽甘来的体验吧哈哈;
好了咋们创建一个webapi项目取名为 Stage.Api ,使用她自动生成的 ValuesController 文件里面的Get方法接口来调用咋们上面实现的博客抓取方法,代码如下:
// GET api/values
public async Task&IEnumerable&MoBlog&& Get(int task = 6)
task = task &= 0 ? 6 :
task = task & 50 ? 50 :
IBlogsReposity _reposity = new BoKeYuan();
return await _reposity.GetBlogs(task);
这里使用 IBlogsReposity _reposity = new BoKeYuan(); 来创建和调用具体的实现类,这里贴出一个线上抓取博客首页信息的地址(不要告诉dudu):;咋们来想象一下,如果这个Get方法中还需要调用其他实现了接口 IBlogsReposity 的博客抓取类,那咋们又需要手动new一次来创建对应的对象;倘若除了在 ValuesController.cs 文件中调用了博客数据抓取,其他文件还需要这抓取数据的业务,那么又会不停的new,可能有朋友就会说那弄一个工厂模式怎么样,不错这是可行的一种方式,不过这里还有其他方法能处理这种问题,比如:ioc依赖注入;因此就有了下面的分享内容。
& IOC框架Ninject的使用
首先,我们要使用ninject需要使用nuget下载安装包,这里要注意的是Ninject版本比较多,需要选择合适自己webapi的版本,我这里选择的是:
看起来很老了哈哈,不过咋们能用就行,安装起来可能需要点时间,毕竟比较大么也有可能是网络的问题吧;安装完后咋们创建一个自定义类 NinjectResolverScope 并实现接口 IDependencyScope , IDependencyScope 对应的类库是 System.Web.Http.dll (注:由于webapi2项目自动生成时候可能勾选了mvc,mvc框架里面也包含了一个IDependencyScope,所以大家需要注意区分下),好了咋们来直接看下 NinjectResolverScope 实现代码:
/// &summary&
/// &/summary&
public class NinjectResolverScope : IDependencyScope
private IResolutionR
public NinjectResolverScope() { }
public NinjectResolverScope(IResolutionRoot root)
this.root =
public object GetService(Type serviceType)
return root.TryGet(serviceType);
catch (Exception ex)
public IEnumerable&object& GetServices(Type serviceType)
return this.root.GetAll(serviceType);
catch (Exception ex)
return new List&object&();
public void Dispose()
var disposable = this.root as ID
if (disposable != null)
disposable.Dispose();
this.root =
这里要注意的是GetService和GetServices方法必须使用& try...catch() 包住,经过多方调试和测试,这里面会执行除手动bind绑定外的依赖,还会执行几个其他非手动绑定的实例对象,这里使用try避免抛异常影响到程序(其实咋们可以在这里用代码过滤掉非手动绑定的几个实例);这里也简单说下这个 NinjectResolverScope 中方法执行的先后顺序:GetService=》GetServices=》Dispose,GetService主要用来获取依赖注入对象的实例;好了到这里咋们还需要一个自定义容器类 NinjectResolverContainer ,该类继承自上面的 NinjectResolverScope 和实现 IDependencyResolver 接口(其实细心的朋友能发现这个 IDependencyResolver 同样也继承了 IDependencyScope ),具体代码如下:
public class NinjectResolverContainer : NinjectResolverScope, IDependencyResolver
private IK
public static NinjectResolverContainer Current
var container = new NinjectResolverContainer();
container.Initing();
container.Binding();
/// &summary&
/// 初始化kernel
/// &/summary&
void Initing()
kernel = new StandardKernel();
/// &summary&
/// &/summary&
void Binding()
kernel.Bind&IBlogsReposity&().To&BoKeYuan&();
/// &summary&
/// 开始执行
/// &/summary&
/// &returns&&/returns&
public IDependencyScope BeginScope()
return new NinjectResolverScope(this.kernel.BeginBlock());
这里能够看到 IKernel kernel = new StandardKernel(); 这代码,她们引用都来源于我们安装的Ninject包,通过调用初始化Initing()后,我们需要在Binding()方法中手动绑定我们对应需要依赖注入的实例,Ninject绑定方式有很多种这里我用的格式是: kernel.Bind&接口&().To&实现类&(); 如此简单就实现了依赖注入,每次我们需要添加不同的依赖项的时候只需要在这个Binding()中使用Bind&接口&.To&接口实现类&()即可绑定成功;好了为了验证咋们测试成功性,我们需要在apiController中使用这个依赖关系,这里我使用构造函数依赖注入的方式:
private readonly IBlogsReposity _reposity
public ValuesController(IBlogsReposity reposity)
_reposity =
// GET api/values
public async Task&IEnumerable&MoBlog&& Get(int task = 6)
task = task &= 0 ? 6 :
task = task & 50 ? 50 :
return await _reposity.GetBlogs(task);
代码如上所示,我们运行下程序看下效果:
这个时候提示了个错误“没有默认构造函数”;我们刚才使用的构造函数是带有参数的,而自定义继承的 ApiController 中有一个无参数的构造函数,根据错误提示内容完全无解;不用担心,解决这个问题只需要在 WebApiConfig.cs 中Register方法中增加如下代码:
//Ninject ioc
config.DependencyResolver = NinjectResolverContainer.C
这句代码意思就是让程序执行上面咋们创建的容器 NinjectResolverContainer ,这样才能执行到我能刚才写的ioc程序,才能实现依赖注入;值得注意的是 config.DependencyResolver 是webapi自带的提供的,mvc项目也有同样提供了 DependencyResolver& 给我们使用方便做依赖解析;好了这次我们在运行项目可以得到如图效果:
& IOC框架Unity的使用
首先,安装Unity和Unity.WebAPI的nuget包,我这里的版本是:
我们再同样创建个自定义容器类 UnityResolverContainer ,实现接口 IDependencyResolver (这里和上面Ninject一样);然后这里贴上具体使用Unity实现的方法:
public class UnityResolverContainer : IDependencyResolver
private IUnityContainer _
public UnityResolverContainer(IUnityContainer container)
this._container =
public IDependencyScope BeginScope()
var scopeContainer = this._container.CreateChildContainer();
return new UnityResolverContainer(scopeContainer);
/// &summary&
/// 获取对应类型的实例,注意try...catch...不能够少
/// &/summary&
/// &param name="serviceType"&&/param&
/// &returns&&/returns&
public object GetService(Type serviceType)
//if (!this._container.IsRegistered(serviceType)) { }
return this._container.Resolve(serviceType);
public IEnumerable&object& GetServices(Type serviceType)
return this._container.ResolveAll(serviceType);
return new List&object&();
public void Dispose()
if (_container != null)
this._container.Dispose();
this._container =
&这里和使用Ninject的方式很类似,需要注意的是我们在安装Unity包的时候会自动在 WebApiConfig.cs 增加如下代码:
//Unity ioc
UnityConfig.RegisterComponents();
然后同时在 App_Start 文件夹中增加 UnityConfig.cs 文件,我们打开此文件能看到一些自动生成的代码,这里我们就可以注册绑定我们的依赖,代码如:
public static class UnityConfig
public static void RegisterComponents()
var container = new UnityContainer();
container.RegisterType&IBlogsReposity, BoKeYuan&();
// var lifeTimeOption = new ContainerControlledLifetimeManager();
//container.RegisterInstance&IBlogsReposity&(new BoKeYuan(), lifeTimeOption);
GlobalConfiguration.Configuration.DependencyResolver = new UnityResolverContainer(container);
这里展示了两种注册依赖的方式: container.RegisterType&IBlogsReposity, BoKeYuan&(); 和 container.RegisterInstance&IBlogsReposity&(new BoKeYuan(), lifeTimeOption); ,当然还有其他的扩展方法这里就不举例了;最后一句代码: GlobalConfiguration.Configuration.DependencyResolver = new UnityResolverContainer(container); 和我们之前Ninject代码一样,只是换了一个地方和实例化写法方式而已,各位可以仔细对比下;其实 UnityConfig.cs 里面的内容都可以移到 WebApiConfig.cs 中去,unity自动分开应该是考虑到代码内容分块来管理吧,好了同样我们使用自定义的 ValuesController 的构造函数来添加依赖:
public class ValuesController : ApiController
private readonly IBlogsReposity _
public ValuesController(IBlogsReposity reposity)
_reposity =
// GET api/values
public async Task&IEnumerable&MoBlog&& Get(int task = 6)
task = task &= 0 ? 6 :
task = task & 50 ? 50 :
return await _reposity.GetBlogs(task);
从代码上来看,这里面Ninject和Unity的注入方式没有差异,这样能就让我们开发程序的时候两种注入方式可以随便切换了,最后来我这里提供一个使用这个webapi获取数据绑定到页面上的效果:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具登录 | 注册
没有账号?
下次自动登录
哪种依赖注入方式你建议使用,构造器注入,还是 Setter方法注入
00:00/00:20}

我要回帖

更多关于 spring 构造注入 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信