【Spring】IOC之方法注入

方法注入在我看来就是为了实现在单例类中取得不同的实例类对象。

当一个Bean依赖的Bean和自己生命周期不同的时候:如Bean A依赖Bean B,Bean A 是singleton,如果需要在Bean A每次用到Bean B的时候都用一个Bean B的新的实例(注意是新的),即使通过在配置文件设置Bean B的 property或者 contructor-arg是不能实现的.这时候只能在Bean A中用Bean B的时候动态得到。

或者可以这么说, 调用一个singleton类型bean A的某个方法时,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的的bean B实例。幸运的是,Spring提供了如下三种解决的方案:

  • 放弃控制反转:通过实现ApplicationContextAware接口让bean A能够感知bean 容器,并且在需要的时候通过使用getBean("B")方式向容器请求一个新的bean B实例。
  • Lookup方法注入:Lookup方法注入利用了容器的覆盖受容器管理的bean方法的能力,从而返回指定名字的bean实例。
  • 自定义方法的替代方案:该注入能使用bean的另一个方法实现去替换自定义的方法。

放弃控制反转的方法比较不方便,一般都不会这么做,所以这里我就不讲了,下面还是来看看lookup方法和replace方法吧!

一、lookup方法注入

Lookup方法注射指容器能够重写容器中bean的抽象或具体方法,返回查找容器中其他bean的结果。 被查找的bean在上面描述的场景中通常是一个non-singleton bean (尽管也可以是一个singleton的)。Spring通过使用CGLIB库在客户端的类之上修改二进制码, 从而实现上述的场景要求。

理解:“Lookup方法”可以使Spring替换一个bean原有的,获取其它对象具体的方法,并自动返回在容器中的查找结果。

下面来看看个例子吧。

定义一个House.java:

package com.mucfc;
public class House {
	private String houseSize;
	private String housePosition;
	private String housePrice;
	public String getHouseSize() {
		return houseSize;
	}
	public void setHouseSize(String houseSize) {
		this.houseSize = houseSize;
	}
	public String getHousePosition() {
		return housePosition;
	}
	public void setHousePosition(String housePosition) {
		this.housePosition = housePosition;
	}
	public String getHousePrice() {
		return housePrice;
	}
	public void setHousePrice(String housePrice) {
		this.housePrice = housePrice;
	}
	public String toString(){
		return "房子大小:"+houseSize+" 房子位置:"+housePosition+" 房子价格:"+housePrice;
	}
}

然后定义一个每次都获得一个house对象的类MaginHouse.java,

public interface MaginHouse {
	House getHouse();
}

再新建一个beans.xml:

添加如下内容:

	<!-- House的一个实例bean,定义每次返回不同的实例对象 -->
	<bean id="house1" class="com.mucfc.House" p:houseSize="200坪"
		p:housePosition="深南花园" p:housePrice="10万" scope="prototype" />
	<!-- 实施方法注入 -->
	<bean id="maginHouse" class="com.mucfc.MaginHouse">
		<lookup-method name="getHouse" bean="house1" />
	</bean>

最后来测试看看:

                ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		MaginHouse maginHouse=applicationContext.getBean("maginHouse",MaginHouse.class);
		House house1=maginHouse.getHouse();
		House house2=maginHouse.getHouse();
		System.out.println(house1);
		System.out.println(house2);
		System.out.println("house2==house1?:"+(house2==house1));
		HouseAgent1 houseagent1=applicationContext.getBean("houseagent1",HouseAgent1.class);
		House house3=houseagent1.getHouse();
		System.out.println(house3);

输出结果:

通过判断我们发现house1和house2是不同的实例。深南花园要是真那么便宜就好了哇!!!

二、方法替换

使用一个bean里的方法去替换另一个bean里的方法。

假设原本有个房子中介HouseAgent1.java,它的定义如下:

package com.mucfc;

public class HouseAgent1 {
	public House getHouse(){
		House house=new House();
		house.setHousePosition("松坪山村");
		house.setHouseSize("200坪");
		house.setHousePrice("4万");
		return house;
	}

}

然后我们要替换HouseAgent1.java里的getHouse()方法。这里需要再定义一个房子中介HouseAgent2.java:

package com.mucfc;
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.MethodReplacer;
public class HouseAgent2 implements MethodReplacer{

	@Override
	public Object reimplement(Object arg0, Method arg1, Object[] arg2)
			throws Throwable {
		House house=new House();
		house.setHousePosition("松坪山村");
		house.setHouseSize("300坪");
		house.setHousePrice("8万");
		return house;
	}
}

然后到beans.xml增加如下代码:

	<!-- 实施方法替换 -->
	<bean id="houseagent1" class="com.mucfc.HouseAgent1">
	<replaced-method name="getHouse" replacer="houseagent2"/>
	</bean>
	<bean id="houseagent2" class="com.mucfc.HouseAgent2"/>

最后来测试看看:

//还没有进行方法替换
		HouseAgent1 houseagent1_1=new HouseAgent1();
		House house3=houseagent1_1.getHouse();
		System.out.println("-----------------HouseAgent1未进行方法替换之前-------------------");
		System.out.println(house3);
		//进行方法替换之后
		HouseAgent1 houseagent1_2=applicationContext.getBean("houseagent1",HouseAgent1.class);
		House house4=houseagent1_2.getHouse();
		System.out.println("-----------------HouseAgent1进行方法替换之后-------------------");
		System.out.println(house4);

效果如下:

看到了没,我们成功的用HouseAgent2.java里的getHouse方法替换了HouseAgent1.java里的getHouse方法,是不是很神奇呢?

三、总结

Lookup方法注入干净整洁,易于扩展,更符合Ioc规则,所以尽量采用这种方式。

时间: 2024-08-05 19:18:31

【Spring】IOC之方法注入的相关文章

spring ioc三种注入方式

spring ioc三种注入方式 IOC ,全称 (Inverse Of Control) ,中文意思为:控制反转 什么是控制反转? 控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术. 由容器控制程序之间的关系,而不是由代码直接控制 由于控制权由代码转向了容器,所以称为反转 接口注入 Setter 注入 构造器注入 三种依赖注入方式的比较 : 接口注入: 接口注入模式因为历史较为悠久,在很多容器中都已经得到应用.但由于其在灵活性.易用性上不如其他两种注入模式,因而在 IOC 的专题世界

Spring 4.2 方法注入解决单例Bean的原型Bean依赖问题

当你在单例Bean中使用原型Bean依赖时,注意,依赖在实例化时解析.因此,如果你依赖注入一个原型Bean到单例Bean中,新的原型Bean被实例化然后依赖注入到单例Bean中.提供给单例Bean的原型实例是唯一的. 然而,假设你想单例Bean在运行时多次获取一个新的原型Bean的实例.你不能依赖注入一个原型Bean到你的单例Bean中,因为注入只发生一次,当Spring容器实例化单例Bean时解析并注入它的依赖.如果你在运行时多次需要一个新的原型Bean,可以使用方法注入. 在大多数应用程序情

关于Spring IOC (DI-依赖注入)

<Spring入门经典>这本书无论对于初学者或者有经验的工程师还是很值一看的,最近花了点时间回顾了Spring的内容,在此顺带记录一下,本篇主要与spring IOC相关 ,这篇博文适合初学者也适合spring有过开发经验的工程师,前者可用于全面了解Spring IOC的知识点,后者且过目进而查漏补缺,ok~,以下是主要内容: Spring IOC 的原理概述 快速入门案例 Spring 容器装配BeanXML配置方式和注解配置方式 Spring 依赖注入 Setter注入 构造函数注入 循环

Spring Ioc和依赖注入

总结一下近来几天的学习,做个笔记 以下是Spring IoC相关内容: IoC(Inversion of Control):控制反转: 其主要功能可简单概述为:将 用 new 去创建实例对象,转换为让Spring通过配置xml文件去创建实例化 对象. 其实现原理大致为: 配置xml文件,通过解析xml文件,利用工厂模式和Java反射机制,实现对象实例的创建. 这一系列过程只需要我们配置相应的xml文件即可,其他的实现交由Spring容器. DI(Dependency Injection):依赖注

Spring IOC容器中注入bean

一.基于schema格式的注入 1.基本的注入方式 (属性注入方式) 根据setXxx()方法进行依赖注入,Spring只会检查是否有setter方法,是否有对应的属性不做要求 <bean id="student" class="com.lq.ioc.Student"> <property name="name" value="zhansan"></property> <propert

浅析Spring IOC、依赖注入(DI)和依赖查找(DL)

为什么要用IOC? 第一:对象的实例化不是一件简单的事情,比如对象的关系比较复杂,依赖关系往往需要程序员去维护,这是一件非常头疼的事. 第二:解耦,由容器去维护具体的对象 第三:托管了类的产生过程,比如我们需要在类的产生过程中做一些处理,最直接的例子就是代理,如果有容器程序可以把这部分过程交给容器,应用程序则无需去关心类是如何完成代理的 控制反转(Inverse of Control) 控制反转即IoC(Incersion of Control),从字面上理解就是控制反转,将对在自身对象中的一个

【SSH系列】深入浅出spring IOC中三种依赖注入方式

spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控制什么?依赖注入和控制反转是一样的概念吗?接触新的知识,小编的脑袋中全是大大的问号,不过没有关系,今天这篇博文,小编主要来简单的介绍一下在spring IOC中依赖注入的方法. 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性.我们可以从以下几个方面理解: a.参与者都

Spring IOC的三种注入方式

Spring IOC三种注入方式: 1.    接口注入 2.    getter,setter方式注入 3.    构造器注入 对象与对象之间的关系可以简单的理解为对象之间的依赖关系:A类需要B类的一个实例来进行某些操作,比如在A类的方法中需要调用B类的方法来完成功能,叫做A类依赖于B类.控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术,由容器控制程序之间的关系,而不是由代码直接控制. 1.接口注入 public class ClassA {  private InterfaceB

Java面试--Spring技术要点--Spring IOC

7  Spring IOC(依赖注入)的方式 Setter方法注入 构造器方法注入 工厂方法注入(实例工厂/静态工厂) 自动装配(需要开启配置,不建议使用) http://blessht.iteye.com/blog/1162131 8  IOC方式建议(构造器注入还是 Setter方法注入) 两种依赖方式都可以使用,构造器注入和Setter方法注入.最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖. 9  什么是Spring beans Springbeans是那些形成S