Spring IoC学习

基本概念

IoC(Inversion of Control),即,创建对象实例的控制权从程序员的代码控制剥离到IOC容器控制,由xml等文件控制,语义侧重于原理。使用Ioc,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。

IoC还可以以“依赖注入DI(Dependency Injection)”解释,即,组件之间的依赖关系由容器在运行期决定,即,意味着由容器动态地将某种依赖关系注入到组件之中,创建对象实例时,为这个对象注入属性值或其他对象实例,语义侧重于实现。

IoC场景

下面以找恋爱对象为例。
Lily大学毕业后直接去工作,然而一直没有男朋友,看着同学们结婚的结婚,谈恋爱的谈恋爱,就想找个男朋友。 Lily想找到对象可以有3种方案:主动寻找Or 同事介绍 Or 父母安排。如何选择?

在这里插入图片描述
主动寻找方式,new一个对象:
在这里插入图片描述


public class Girl { 
  public void love(){ 
    Boy boy = new Boy(); 
  } 
 

同事介绍(男孩工厂):
在这里插入图片描述

public class Girl { 
  void love(){ 
    Boy boy = BoyFactory.createBoy(); 
  } 
} 

父母安排:
在这里插入图片描述


public class Girl { 
  void love(Boy boy){ 
   boy.love(); 
  } 
}

在Spring世界里,跟Lily最后的选择一样,由父母安排恋爱对象,这就是控制反转,而这里具有控制力的父母,即是Spring容器。

IoC注入方式

IoC主要有2种注入方式:接口注入、Setter方法注入、构造器注入。
虽然接口注入模式在很多容器中都已经得到应用,但由于其在灵活性、易用性上不如其他两种注入模式,因而在IOC中已经被废弃。
Spring的5.1.5.RELEASE中的文档上说:

 DI exists in two major variants:
 Constructor-based dependency injection and Setter-based dependency injection

接口注入其实也是通过Setter注入来实现:

interface BoyInterface{
    public void injectHere(Boy bf);
}

class Company implements BoyInterface {
   Boy BoyInterface;; 

   public void injectHere(Boy bf) {
        this.BoyInterface = bf;
    }
}

Girl类:

package ioc;

public class Girl {
	private Boy bf;
	public Girl () {
		
	}
	public Girl(Boy bf) {
		System.out.println("构造方法注入:");
		this.bf=bf;
	}
	public void setBf(Boy bf) {
		System.out.println("Setter注入:");
		this.bf=bf;
	}
	public void loveBoy() {
		bf.love();
	}
}


Boy类:

package ioc;

public class Boy {
	public void love() {
		System.out.println("Love me!");
	}
	
}

Main方法:

package ioc;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		ApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml");
		Girl lili=(Girl)factory.getBean("girl");
		lili.loveBoy();

	}

}


applicationContext.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"
	     xmlns:aop="http://www.springframework.org/schema/aop"
	     xmlns:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
 			<!--default-autowire="byName"-->
 			<!--&gt;-->
	<bean id="boy" class="ioc.Boy" />
	<bean id="girl" class="ioc.Girl">
		<!--构造器注入-->
		<constructor-arg ref="boy"></constructor-arg>
		<!--Setter方法注入-->
		<!-- property name="bf" ref="boy"></property> -->
	</bean>

</beans>

applicationContext.xml配置文件(Setter byName):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	     xmlns:aop="http://www.springframework.org/schema/aop"
	     xmlns:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
 			default-autowire="byName"
 			>
	<bean id="boy" class="ioc.Boy" />
	<bean id="girl" class="ioc.Girl">
		<!--构造器注入-->
		<!--<constructor-arg ref="boy"></constructor-arg>-->
		<!--Setter方法注入-->
		 <property name="bf" ref="boy"></property>
	</bean>
</beans>

Setter方法注入时,有2种装载方式——byName和byType。当使用byType方式装载时,Spring是根据classType来确定要实例化的类,无需关注bean的id是什么,即使和Girl中bf的Setter方法名不一致,依旧可以实例化。但是使用byName时,则是根据id来实例化类,所以需要把Boy类对应的bean id跟Girl中的Setter方法名一致才行,即修改bean id="boy"为id="bf"或者注入属性值。

applicationContext.xml配置文件(Setter byType):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	     xmlns:aop="http://www.springframework.org/schema/aop"
	     xmlns:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
 			default-autowire="byType"
 			>
	<bean id="boy" class="ioc.Boy" />
	<bean id="girl" class="ioc.Girl">
		<!--构造器注入-->
		<!--<constructor-arg ref="boy"></constructor-arg>-->
		<!--Setter方法注入-->
		 <!--<property name="bf" ref="boy"></property>-->
	</bean>
</beans>

注入方式比较

Setter 注入:

1、通过 setter 方法设定依赖关系更加直观。
2、如果依赖关系较为复杂,那么构造子注入模式的构造函数也会相当庞大,而此时设值注入模式则更为简洁。
3、如果用到了第三方类库,需要组件提供一个默认的构造函数时,构造子注入模式也不适用。

构造器注入:

1、在构造期间完成一个完整的、合法的对象。
2、所有依赖关系在构造函数中集中呈现。
3、依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。
4、只有组件的创建者关心其内部依赖关系,对调用者而言,该依赖关系处于“黑盒”之中,无需知晓。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值