在大部分情况下,IoC容器中的bean都是singleton类型的。如果一个singleton bean要引用另一个singleton bean,或者一个非singleton bean要引用另外一个singleton bean时,通常情况下将一个bean定义为另一个bean的property值就可以了。不过对于具有不同生命周期的bean来说这样做会有问题,比如在调用一个singleton类型的bean A的某个方法的时候,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的bean B实例。
上述问题的一个解决办法就是放弃控制反转。通过实现BeanFactoryAware接口让bean A能够感知bean容器,并且在需要的时候通过使用getBean("B")方式向容器请求一个新的bean B实例。看下面这个例子,其中故意使用了这种方法:
import org.springframework.beans.BeansException;
import org.springframework.context.Applicationcontext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}
上面的例子显然不是最好的,因为业务代码和Spring Framework产生了耦合。方法注入,作为Spring IoC容器的一种高级特性,可以以一种干净的方式来处理这种情况。
Lookup方法注入
Lookup方法注入利用了容器的覆盖受容器管理的bean方法的能力,从而返回指定名字的bean实例。在上述的场景中,Lookup方法注入适用于prototype(原型)bean(尽管也适用于singleton bean,但在那种情况下直接注入一个实例就够了)。Lookup方法注入的内部机制是Spring利用了CGLIB库在运行时生成二进制代码功能,通过动态创建Lookup方法bean的子类而达到复写Lookup方法的目的。
如果你看下上个代码段中的代码(CommandManager类),Spring容器动态覆盖了createCommand()方法的实现。你的CommandManager类不会有一点对Spring的依赖,在下面这个例子中也是一样的:
// no more Spring imports!
public abstract class CommandManager {
public Object process(Object commandState) {
// grab a new instance of the appropriate Command interface
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
}
在包含被注入方法的客户类中(此处是CommandManager),此方法的定义必须按照以下形式进行:
<public|protected> [abstract] <return-type> theMethodName(no-arguments);
如果方法是抽象的,动态生成的子类会实现该方法。否则,动态生成的子类会覆盖类里面的具体方法。让我们来看个例子:
<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="command" class="AsyncCommand" scope="prototype">
<!-- inject dependencies here as required -->
</bean>
<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="CommandManager">
<lookup-method name="createCommand" bean="command"/>
</bean>
在上面的例子中,标识为commandManager的bean在需要一个新的coummand bean实例时,会调用createCommand方法。重要的一点是,必须将command部署为原型。当然也可以指定为singleton,如果是这样的话,那么每次将返回相同的command bean实例。
Lookup方法注入既可以结合构造器注入,也可以与setter注入相结合。
注意,为了让这个动态子类得以正常工作,需要把CGLIB的jar文件放在classpath里。另外,Spring的容器要子类化的类不能是final的,要覆盖的方法不能是final的。同样的,要测试一个包含抽象方法的类呀稍微有些不同,你需要自己编写它的子类提供抽象方法的实现。最后作为方法注入目标的bean不能是序列化的(serialized)。
自定义方法的替代方案
比起Lookup方法注入,还有一种很少用到的方法注入形式,该注入能使用bean的另一个方法实现去替换自定义的方法。
当使用基于XML配置元数据文件时,可以在bean定义中使用replaced-method元素来达到另一个方法来取代已有方法的目的。考虑下面的类,我们将覆盖computeValue方法:
public class MyValueCalculator {
public String computeValue(String input) {
// some real code...
}
// some other methods...
}
实现org.springframework.beans.factory.support.MethodReplacer接口的类提供了新的方法定义。
/** meant to be used to override the existing computeValue(String)
implementation in MyValueCalculator
*/
public class ReplacementComputeValue implements MethodReplacer {
public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
// get the input value, work with it, and return a computed result
String input = (String) args[0];
...
return ...;
}
}
下满的bean定义中指定了将要复写的方法以及执行替换处理的bean定义:
<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
<!-- arbitrary method replacement -->
<replaced-method name="computeValue" replacer="replacementComputeValue">
<arg-type>String</arg-type>
</replaced-method>
</bean>
<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>
在<replaced-method/>元素内可包含一个或多个<arg-type/>元素,这些元素用来标明被复写的方法签名。只有被复写(override)的方法存在重载(overload)的情况(同名的多个方法变体)才会使用方法签名。为了方便,参数的类型字符串可以采用全限定类名的简写。例如,下面的字符串都表示参数类型为java.lang.String.
java.lang.String
String
Str
参数的个数通常足够用来区别每个可能的选择,这个捷径能减少很多键盘输入的工作,它允许你只输入最短的匹配参数类型的字符串。
分享到:
相关推荐
我们学习了spring框架spring框架里面有3个优势第一个是轻量级的IOC也叫控制反转后来改名为DI也叫依赖注入,依赖注入里面有3中注入方法分别是set注入,构造器注入,注解注入,我传的是set注入的视频
Spring中的方法注入方式.Spring中的方法注入方式.
方法注入图解lookupmethod方法注入图解lookupmethod
Spring IOC之方法注入 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45022649
适用.netfx4的方法注入源码 采用写入方法表内存重新jit编译的方式, 不依赖于注入库,可学习原理
NULL 博文链接:https://zhangyulong.iteye.com/blog/856986
主要给大家介绍了关于spring boot中几种注入方法的一些个人看法,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
(2)使用IOC容器实例化上述类,并对属性使用构造方法注入,然后测试。 (3)模拟三层体系结构,为其创建对应的departmentDao、departmentService、departmentController;实现对部门项目的查询、添加和修改。
2.1构造函数注入:先去容器中找到该接口的实现类型。然后遍历该实现类型的构造函数中的参数。首先找有特性标记的。如果没有特性就找构造参数最多的那个构造函数。然后对这个构造函数里的参数进行实例化。如果该...
C# MVC默认的实例化控制器时是调用不带参数的构造函数,但是使用castle注入进行构造注入构造函数带参。
NULL 博文链接:https://1151461406.iteye.com/blog/2389898
spring练习 刚刚学spring,做了个小小小项目,来加深理解。... ·其他依赖注入属性,都使用property 元素确定参数值。 Person.java PersonFactory.java Chinese.java American.java bean.xml SpringTest.java
对于spring配置一个bean时,如果需要给该bean提供一些初始化参数,则...·使用属性的setter方法注入 ,这是最常用的方式; ·使用构造器注入; 最好的解决方案是用构造器参数实现强制依赖,setter 方法实现可选依赖。
spring注入方式 set注入 构造注入 自动注入
JSP开发之Spring方法注入之替换方法实现 Spring提供了一种替换方法实现的机制,可以让我们改变某个bean某方法的实现。打个比方我们有一个bean,其中拥有一个add()方法可以用来计算两个整数的和,但这个时候我们想把...
主要介绍了详解PHP的Yii框架中组件行为的属性注入和方法注入,包括对依赖注入的讲解,需要的朋友可以参考下
今天有空,写了基于C#使用Spring.Net的演示实例,希望能给有需要的人带来帮助,其中演示了配置下的IOC、AOP、属性注入、构造函数注入、通知过滤器、以及不使用配置直接代码硬编的AOP动态代码过程,另外还增加了...
4.用Get方法注入时,IIS会记录你所有的提交字符串,对Post方法做则不记录,所以能用Post的网址尽量不用Get。 5. 猜解Access时只能用Ascii逐字解码法,SQLServer也可以用这种方法,只需要两者之间的区别即可,...
对于网站的安全性,是每个网站开发者和运营者最关心的问题。网站一旦出现漏洞,那势必将造成很大的损失。为了提高网站的安全性,首先网站要防注入,最重要的是服务器的安全... C#防SQL注入方法一 在Web.config文件中