文档章节

Spring的学习(三):核心机制:依赖注入

yuhuan121
 yuhuan121
发布于 2017/08/24 14:21
字数 1501
阅读 3
收藏 0
点赞 0
评论 0

1、前言

Java应用中经常存在对象A调用对象B方法的情况,这种情况被spring称作依赖,即为A对象依赖B对象。对于java应用来说,它们总是由一些互相调用的对象构成的,Spring把这种调用关系称作依赖关系。若A组件调用了B的方法,称作A组件依赖B组件。 Spring框架的核心功能有两个:

  • spring容器作为超级工厂,负责创建、管理所有的Java对象,这些Java对象被称为bean;
  • spring 容器使用依赖注入的方式来管理容器中Bean之间的依赖关系

2、理解依赖注入

控制反转(IOC):调用者获取被依赖对象的方式由原来的主动获取变为现在的被动接受;

依赖注入(DI):spring容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它依赖的实例; 依赖注入通常有两种:

  • 设值注入:IOC容器使用成员变量的setter方法来注入被依赖对象。Bean与Bean之间的依赖关系由Spring管理,Spring采用setter方法为目标Bean注入所依赖的Bean;
  • 构造注入:IOC容器使用构造器来注入被依赖对象;

2.1、设值注入

spring推荐面向接口编程,可以更好的让规范和实现分离,从而实现更好的解耦。在JavaEE中,不管是DAO组件还是业务逻辑组件,都应该先定义一个接口,定义了该接口实现的功能,但功能的实现由实现类提供。

(1)、先定义一个person接口

package org.crazyit.app.service;
public interface Person{
	//定义一个使用斧头的方法
	public void useAxe();
}

(2)、再定义一个Axe接口

package org.crazyit.app.service;

public interface Axe {
	//定义一个砍的方法
	public String chop();
}

(3)、Person类的实现代码

package org.crazyit.app.service.impl;

import org.crazyit.app.service.Axe;
import org.crazyit.app.service.Person;

public class Chinese implements Person{
	private Axe axe;
	//设值注入所需要的setter方法
	public void setAxe(Axe axe){
		this.axe = axe;
	}
	// 实现Person接口的useAxe方法
	public void useAxe() {
		//调用axe的chop方法
		//表明person对象依赖与axe对象
		System.out.println(axe.chop());	
	}
}

此时,Chinese类不知道它调用的Axe实例在哪,也不知道Axe实例是怎么实现的,它只需要调用Axe实例的方法即可。Axe实例由spring容器负责注入。

(4)、Axe的实现类如下:

package org.crazyit.app.service.impl;

import org.crazyit.app.service.Axe;

public class StoneAxe implements Axe{

	@Override
	public String chop() {	
		return "石斧砍柴好慢!";
	}
	
}

程序依然不知道Chinese类和哪个Axe实例耦合,这是就需要Spring使用XML文件来指定实例之间的依赖关系

(5)、配置文件beans.xml

<?xml version="1.0" encoding="UTF-8"?>
 <!--  Spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 --> 
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<!-- 配置chinese实例,其实现类是Chinese类 -->
	<bean id="chinese" class="org.crazyit.app.service.impl.Chinese">
		<!--  驱动调用chinese的setAxe()方法,将容器中stoneAxe作为传入参数  -->
	    <property name="axe" ref="stoneAxe"/>
    </bean>
    <!-- 配置stoneAxe实例,其实现类是StoneAxe -->
    <bean id="stoneAxe" class="org.crazyit.app.service.impl.StoneAxe"/>
</beans>

Spring配置Bean实例通常会指定两个属性:

  • id :这是指定该Bean的唯一标识。Spring通过id属性值来管理该Bean之间的依赖,程序通过它来访问该Bean的实例;
  • class:指定该Bean的实现类,这时候不能再用接口,必须为其实现类。Spring会使用XML解析器来读取该属性值,并利用反射来创建该实现类的实例;

<property>是<bean>的子元素,它驱动spring在底层以反射方式来执行一次setter方法。name属性决定执行那个setter方法,value和ref决定执行setter方法的执行参数。

  • 如果传入参数是基本类型及其包装类、String等类型,用value属性指定传入参数;
  • 如果以容器中其他Bean类型作为传入参数,则用ref;

(6)、主程序代码BeanTest.java

package lee;

import org.crazyit.app.service.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanTest {

	public static void main(String[] args) throws Exception {
	//创建spring容器
	ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
	//获取person实例
	Person p = ctx.getBean("chinese", Person.class);
	//调用useAxe方法
	p.useAxe();
	}
}

run as后得到 输入图片说明

(7)、文件目录示意图

输入图片说明

2.2、构造注入

本质:驱动Spring在底层以反射方式执行带指定参数的构造器,此时,可以利用构造器参数对成员变量执行初始化;

(1)、修改上面的Chinese类

package org.crazyit.app.service.impl;

import org.crazyit.app.service.Axe;
import org.crazyit.app.service.Person;

public class Chinese implements Person{
	private Axe axe;
	//构造注入所需的带参数的构造器
	public Chinese (Axe axe){
		this.axe = axe;
	}
	// 实现Person接口的useAxe方法
	public void useAxe() {
		//调用axe的chop方法
		//表明person对象依赖与axe对象
		System.out.println(axe.chop());	
	}
}

(2)、修改配置文件 <bean>默认驱动Spring调用无参的构造器来创建对象,也可以使用<constrctor-arg../>子元素来驱动Spring调用有参数的构造器来创建对象。每个<constrctor-arg../>子元素代表一个构造器参数。

把上面的beans.xml修改如下:

<?xml version="1.0" encoding="UTF-8"?>
 <!--  Spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 --> 
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
	<!-- 配置chinese实例,其实现类是Chinese类 -->
	<bean id="chinese" class="org.crazyit.app.service.impl.Chinese">
		<!--  下面只有一个constructor-arg子元素,驱动spring调用Chinese带一个参数的构造器来创建对象  -->
	    <constructor-arg ref="stoneAxe"/>
    </bean>
    <!-- 配置stoneAxe实例,其实现类是StoneAxe -->
    <bean id="stoneAxe" class="org.crazyit.app.service.impl.StoneAxe"/>
</beans>

2.3、区别

比如在此例中,就是创建Person实例中Axe属性的时机不同

  • 设置注入是先通过调用无参数的构造器来创建一个Bean实例,然后调用对应的setter方法来进行注入依赖关系
  • 构造注入是直接调用有参数的构造器,当Bean实例创建完成后,也完成了依赖关系的注入

© 著作权归作者所有

共有 人打赏支持
yuhuan121
粉丝 0
博文 36
码字总数 38704
作品 0
佛山
程序员
spring 入门及IOC容器

Spring 一.Spring,原意“春天”,是一种轻量级容器框架,所谓轻量级就是依赖比较少,侵入性较低,其核心就是1. IOC(Inversion of Control)/DI(Dependency Injection)IoC的核心思想是通过消...

天国使者125
2013/06/15
0
0
Spring实战 (一) 一切从Bean开始

Spring可以做很多事情,但是归根究底.Spring的核心仅仅是依赖注入(DI)/控制反转(IoC)和面向切面编程(AOP)而已.Spring的一切都是基于这2点 Spring的一切都是从Bean开始的.什么是Bean?凡是被Spr...

kenshiro
2013/09/05
0
0
spring ioc 和 aop-----一些小结

话说,学习spring也快大半年了,写业务层代码也写了半年之久了,对于spring中的一些核心技术现在还是似懂非懂的,很是纠结啊。。。 最近一直看别人写的对于这一块的理解,于是乎,我有点懂了...

bosscheng
2013/05/22
0
0
Spring学习笔记1——基础知识

1.在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书《Expert one-on-one J2EE Design and Development》和《Expert one-on-one J2EE deve...

李长春
2011/10/09
0
0
1000行代码读懂Spring(一)- 实现一个基本的IoC容器

引言 最近在读Spring源码,但是Spring代码层次嵌套太多,读起来有很大跳跃性,我有个朋友甚至开玩笑说,读Spring得拿纸笔,把方法和层次都写下来。 其实Spring我已经接触很久了,记得大学有个...

黄亿华
2014/01/13
0
37
基于Struts+Spring+Hibernate的使用和部署

就现在WEB开发而言,J2EE企业级开发技术比较成熟,开发模式模式也比较繁多,较流行开发模式MVC更是普遍,而基于MVC模式开发的框架也是种类繁多,现在使用最多的可能就是SSH这三种框架,所以展...

chenruibing
2015/08/18
0
0
Spring中依赖注入的四种方式

在Spring容器中为一个bean配置依赖注入有三种方式: · 使用属性的setter方法注入 这是最常用的方式; · 使用构造器注入; · 使用Filed注入(用于注解方式). 使用属性的setter方法注入 首...

Zero零_度
2015/04/07
0
0
Struts,Hibernate,Spring经典面试题收藏

Struts,Hibernate,Spring经典面试题收藏 以备不时只需。 关键字: struts, hibernate, spring 先简单的提一下, 要开发出好的,高质量的j2ee系统, 评价系统的高低水平 ,解耦性 至关重要!...

dengzhangtao
2010/12/06
0
0
spring面试题 对DI , AOP概念的理解

spring 的优点? 1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易...

罗荣熙
2012/11/12
0
0
spring ioc 学习(1)

如果用通俗易懂的语言让一个完全不懂计算机的人理解你所谓的技术,那么说明你真的懂了。这句话是我曾经的一个师傅告诉我的... spring最大的魅力是IOC、AOP这个是业内公认的了..所以,站在巨人...

五岳儿爸
2012/01/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

命令

sudo nginx -s reload 重启nginx sudo lsof -i -P | grep -i "listen" 查看端口占用

那个猴子
4分钟前
0
0
用scrapy-redis爬去新浪-以及把数据存储到

需求:爬取新浪网导航页(http://news.sina.com.cn/guide/)所有下所有大类、小类、小类里的子链接,以及子链接页面的新闻内容。 准备工作: a.安装redis(windows或者linux) b.安装Redis Des...

丁典
4分钟前
0
0
PHP常用函数篇

1.为什么要使用函数? 除了内建的PHP函数,我们可以创建我们自己的函数。 函数是可以在程序中重复使用的语句块。 使代码逻辑更清晰 避免过多的全局变量 封装后避免相同逻辑重复代码,只需调用...

天地有涯风有信_大海无量不见人
5分钟前
0
0
对List分组

在日常工作中会遇到这样的情景,我们需要对List按照List中对象的一个值进行分组。比如一个Human的List,我们要根据性别分组,传统的方法是做双层循环,逐个对比,今天我要介绍一种详单简单的...

珂jack
7分钟前
0
0
分析jquery ajax jsonpCallback回调函数名包含点号报错问题

现象 项目中涉及到跨域请求,采用jquery ajax jsonp来实现,但是遇到一个奇怪问题,在设置回调函数名称时,若包含点号,如“Callback.Success”,那么执行完成后,其error回调函数始终会被触...

iwaller
10分钟前
0
0
【Graphql实践】使用 Apollo(iOS) 访问 Github 的 Graphql API

最近在协助调研 Apollo 生成的代码是否有可能跨 Query 共享模型的问题,虽然初步结论是不能,并不是预期的结果,但是在调研过程中积累的一些经验,有必要记录下。如果你也对 Graphql 感兴趣,...

ios122
10分钟前
1
0
聊聊spring cloud的AsyncLoadBalancerAutoConfiguration

序 本文主要研究一下AsyncLoadBalancerAutoConfiguration AsyncLoadBalancerAutoConfiguration spring-cloud-commons-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/client/loadba......

go4it
20分钟前
0
0
10.19 iptables规则备份和恢复 ,firewalld的9个zone,service的操作

保存和备份iptables规则 内容: 保存iptables规则 service iptables save 把iptables规则备份到my.ipt文件中: iptables-save > my.ipt 恢复刚才备份的规则: iptables-restore < my.ipt 1.......

Linux_老吴
22分钟前
0
0
Vue 自动化表单相关资料

1.使用vue自动化表单 2.Vue可视化,Vue代码生成,Vue动态表单 3.前端表单进阶之路:通过 Vue.js 实现表单可配置化 4.使用Vue动态生成form表单 5.autoform-devtool 6.Vue.js实践:实现多条件筛...

IT追寻者
23分钟前
0
0
动态SQL

一、动态SQL 1、if <select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title l......

一个yuanbeth
26分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部