引言

假设一个单例模式的bean A需要引用另外一个非单例模式的bean B,为了在我们每次引用的时候都能拿到最新的bean B,我们可以让bean A通过实现ApplicationContextWare来感知applicationContext(即可以获得容器上下文),从而能在运行时通过ApplicationContext.getBean(String beanName)的方法来获取最新的bean B。但是如果用ApplicationContextAware接口,就让我们与Spring代码耦合了,违背了反转控制原则(IoC,即bean完全由Spring容器管理,我们自己的代码只需要用bean就可以了)。

所以Spring为我们提供了方法注入的方式来实现以上的场景。方法注入方式主要是通过<lookup-method/>标签。

实例

下面我们用一个例子来说明lookup-method的用法。

假设有一个果盘,果盘里放了一些水果,比如苹果,香蕉等,我们希望我们每次在果盘里拿到的都是最新鲜的水果。

java代码:

// 定义一个水果类
public class Fruit {
public Fruit() {
System.out.println("I got Fruit");
}
} // 苹果
public class Apple extends Fruit {
public Apple() {
System.out.println("I got a fresh apple");
}
} // 香蕉
public class Bananer extends Fruit {
public Bananer () {
System.out.println("I got a fresh bananer");
}
} // 水果盘,可以拿到水果
public abstract class FruitPlate{
// 抽象方法获取新鲜水果
protected abstract Fruit getFruit();
}

spring配置:

<!-- 这是2个非单例模式的bean -->
<bean id="apple" class="cn.com.willchen.test.di.Apple" scope="prototype"/>
<bean id="bananer" class="cn.com.willchen.test.di.Bananer " scope="prototype"/> <bean id="fruitPlate1" class="cn.com.willchen.test.di.FruitPlate">
<lookup-method name="getFruit" bean="apple"/>
</bean>
<bean id="fruitPlate2" class="cn.com.willchen.test.di.FruitPlate">
<lookup-method name="getFruit" bean="bananer"/>
</bean>

测试代码:

public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("classpath:resource/applicationContext.xml"); FruitPlate fp1= (FruitPlate)app.getBean("fruitPlate1");
FruitPlate fp2 = (FruitPlate)app.getBean("fruitPlate2"); fp1.getFruit();
fp2.getFruit();
}

测试结果:

I got Fruit

I got a fresh apple

I got Fruit

I got a fresh bananer

示例说明:

从上面例子我们可以看到,在代码中,我们没有用到Spring的任何类和接口,实现了与Spring代码的耦合。

其中,最为核心的部分就是lookup-method的配置和FruitPlate.getFruit()方法。上面代码中,我们可以看到getFruit()方法是个抽象方法,我们并没有实现它啊,那它是怎么拿到水果的呢。这里的奥妙就是Srping应用了CGLIB(动态代理)类库。Spring在初始化容器的时候对配置<lookup-method/>的bean做了特殊处理,Spring会对bean指定的class做动态代理,代理<lookup-method/>标签中name属性所指定的方法,返回bean属性指定的bean实例对象。每次我们调用fruitPlate1或者fruitPlate2这2个bean的getFruit()方法时,其实是调用了CGLIB生成的动态代理类的方法。关于CGLIB大家可自行在网上查阅。

lookup-method实现方式说明:

<bean class="beanClass">
<lookup-method name="method" bean="non-singleton-bean"/>
</bean>

method是beanClass中的一个方法,beanClass和method是不是抽象都无所谓,不会影响CGLIB的动态代理,根据项目实际需求去定义。non-singleton-bean指的是lookup-method中bean属性指向的必须是一个非单例模式的bean,当然如果不是也不会报错,只是每次得到的都是相同引用的bean(同一个实例),这样用lookup-method就没有意义了。

另外对于method在代码中的签名有下面的标准:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

public|protected要求方法必须是可以被子类重写和调用的;

abstract可选,如果是抽象方法,CGLIB的动态代理类就会实现这个方法,如果不是抽象方法,就会覆盖这个方法,所以没什么影响;

return-type就是non-singleton-bean的类型咯,当然可以是它的父类或者接口。

no-arguments不允许有参数。

Spring - lookup-method方式实现依赖注入的更多相关文章

  1. Java Spring学习笔记----Bean的依赖注入(设值注入方式)1

    Spring常用的两种依赖注入方式:一种是设值注入方式,利用Bean的setter方法设置Bean的属性值:另一种是构造注入,通过给Bean的构造方法传递参数来实现Bean的属性赋值: 1.设值注入方 ...

  2. 深入浅出spring IOC中三种依赖注入方式

    深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...

  3. 转:深入浅出spring IOC中四种依赖注入方式

    转:https://blog.csdn.net/u010800201/article/details/72674420 深入浅出spring IOC中四种依赖注入方式 PS:前三种是我转载的,第四种是 ...

  4. Spring理论基础-控制反转和依赖注入

    第一次了解到控制反转(Inversion of Control)这个概念,是在学习Spring框架的时候.IOC和AOP作为Spring的两大特征,自然是要去好好学学的.而依赖注入(Dependenc ...

  5. Spring IOC(三)依赖注入

    本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 1.AbstractBeanFactory ...

  6. spring学习(二)---依赖注入

    spring第二个特性是依赖注入. 学习依赖注入,首先应该明白两个问题:1,谁依赖谁:2,谁注入,注入什么? 首先还是看代码: 还是这个bean: package testSpring.busines ...

  7. 7 -- Spring的基本用法 -- 3... Spring 的核心机制 : 依赖注入

    7.3 Spring 的核心机制 : 依赖注入 Spring 框架的核心功能有两个. Spring容器作为超级大工厂,负责创建.管理所有的Java对象,这些Java对象被称为Bean. Spring容 ...

  8. Spring的自动装配与依赖注入

    Spring的自动装配与依赖注入 装配 = 创建Bean + 注入Bean 创建Bean 自动发现 显式注册Bean 注入Bean 基于配置的注入 自动注入 Spring的装配分为显式装配和隐式装配, ...

  9. IOC和AOP使用扩展 多种方式实现依赖注入

    多种方式实现依赖注入 1.Spring 使用setter访问器实现对属性的赋值, 2.Spring 构造constructor方法赋值, 3.接口注入 4.Spring P命名空间注入直接量 sett ...

  10. Spring IOC(五)依赖注入

    Spring IOC(五)依赖注入 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.autowire 五种注入方式测试 ...

随机推荐

  1. Lua语法要点

    本文在我的独立博客中的链接:https://www.bughui.com/2017/04/01/lua-grammar-points/ 这篇文章其实是我在四月一号发布的,由于我重新注册了一个博客园帐号 ...

  2. RQNOJ 201 奥运大包围:LIS + 拼链成环

    题目链接:https://www.rqnoj.cn/problem/201 题意: 开始时n(n<=1000)个人手拉手围成一个圈. 后来这些人中的一些按顺序向里面出圈形成一个新圈.从而使原圈形 ...

  3. G++与VS2015在变量作用域上的差异性

    前段时间,发现同一段C++代码在windows .Linux下的运行结果居然不一样,于是测试了一把. 我们都知道,C++中不同作用域中不同的变量是互不干扰的,可以在全局作用域.函数作用域声明同样名字的 ...

  4. java web方面的面试问题,Spring MVC方面的面试问题,摘自java web轻量级开发面试教程

    本文摘自java web轻量级开发面试教程: https://baike.baidu.com/item/Java%20Web%E8%BD%BB%E9%87%8F%E7%BA%A7%E5%BC%80%E ...

  5. 同形异义字:看我如何拿到TaoBao.com的解析权

    *本文原创作者:expsky@MS509Team,本文属FreeBuf原创奖励计划 同形异义字钓鱼攻击号称"几乎无法检测",是最狡猾的钓鱼攻击!这种攻击产生的原因是国际化域名IDN ...

  6. opencv VideoCapture使用示例

    在centos7下验证VideoCapture功能. 1 opencv处理视频时要使用ffmpeg,这里使用添加源的方式安装,分为3步 1.1 先安装EPEL Release,使用其他的repo源,所 ...

  7. mapper.xml是怎样实现Dao层接口

    上午写了一个简单的 从xml读取信息实例化一个Bean对象.下午就开始想mybatis是怎么通过xml文件来实现dao层接口的,一开始想直接用Class.forName(String name)然后调 ...

  8. 第一行代码_activity生命周期

    这类文章基本上已经是烂大街了,不过我今天仍然要给自己做一遍梳理,因为通过昨天的项目我发现自己还是不太懂activity的各个生命周期;各位看官勿喷; 七个生命周期及其作用 oncreat 完成初始化操 ...

  9. [2017-05-31]Abp介绍和经验分享-目录

    很久没动博客了,人比较懒. 最近想写点啥,主要就介绍下ABP框架和我这两年的使用经验. 文档翻译之类的工作就算了,需要的请参考: 官方文档 PS:官方文档末尾有中文文档的链接,这里就不贴了 先列个提纲 ...

  10. CAS 单点登陆

    一.Tomcat配置SSL 1. 生成 server key 以命令方式换到目录%TOMCAT_HOME%,在command命令行输入如下命令: keytool -genkey -alias tomc ...