文档章节

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

yuhuan121
 yuhuan121
发布于 2017/08/24 14:21
字数 1501
阅读 3
收藏 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
佛山
程序员
私信 提问
Java笔记——看完这个,打通Spring难度系数

写在前面经过一段时间的整理,希望读者看完后对自己的知识点有所帮助。 写过java的都知道:所有的对象都必须创建;或者说:使用对象之前必须先创建。而使用ioc之后,你就可以不再手动创建对象...

简祥
09/14
0
0
【死磕 Spring】----- IOC 之深入理解 Spring IoC

版权声明:版权声明:转载前请留言获得作者许可,转载后标明作者 chenssy 和原文出处。原创不易,感谢您的支持 https://blog.csdn.net/chenssy/article/details/82343456 在一开始学习 Spri...

chenssy
09/03
0
0
【死磕 Spring】—– IOC 之深入理解 Spring IoC

在一开始学习 Spring 的时候,我们就接触 IoC 了,作为 Spring 第一个最核心的概念,我们在解读它源码之前一定需要对其有深入的认识,本篇为【死磕 Spring】系列博客的第一篇博文,主要介绍 ...

chenssy
09/02
0
0
Spring_总结_03_装配Bean之自动装配

一、前言 本文承接上一节:Spring总结02_依赖注入 在上一节我们了解到依赖注入的实质就是装配。 这一节我们来学习下装配Bean的相关知识。 二、Bean的装配机制 1.三种装配机制 Spring提供了三...

shirayner
07/27
0
0
Java框架 Spring 核心机制

概念 轻量级的(面向切面AOP)、(IOC控制反转)容器框架。 Spring优点 1.降低组件之间的耦合性 2.专注于自己业务逻辑,统一的行为(日志、安全等)抽象出来统一处理 3.易于单元测试 4.方...

java知识分子
09/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CentOS 安装PHP5和PHP7

安装PHP5 下载解压二进制包 [root@test-a src]# cd /usr/local/src/[root@test-a src]# wget http://cn2.php.net/distributions/php-5.6.32.tar.bz2[root@test-a src]# tar jxvf php-5.6......

野雪球
今天
4
0
windows上类似dnsmasq的软件Dual DHCP DNS Server

官网地址:http://dhcp-dns-server.sourceforge.net/官网定向的下载地址:https://sourceforge.net/projects/dhcp-dns-server/files/ 设置参考地址:http://blog.51cto.com/zhukeqiang/18264......

xueyuse0012
今天
3
0
LinkedHashMap源码解析

前言 HashMap中的元素时无序的,也就是说遍历HashMap的时候,顺序和放入的顺序是不一样的。 如果需要有序的Map,就可以采用LinkedHashMap. LinkedHashMap通过维护一个包含所有元素的双向链表,...

grace_233
今天
4
0
初识flask

文档 0.10.1版本 http://www.pythondoc.com/flask/index.html 1.0.2版本 https://dormousehole.readthedocs.io/en/latest/ 安装flask $ pip3 install flaskCollecting flask Downloading......

yimingkeji
昨天
6
0
Akka系统《sixteen》译

Actor是一个封装状态(state)和行为(behavior)的对象,它们只通过交换消息通信(放入收件人邮箱的邮件)。从某种意义上说,Actor是最严格的面向对象编程形式,但它更适合将他们视为人:在与Act...

woshixin
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部