singleton实例依赖于prototype实例,ProtoType含义是无效的,必须钩入向Spring容器请求,也就是调用getBean方法。换句话说,我们必须改变依赖关系的注入。
例如A的scope是 Singleton ,B的scope是Prototype,当A依赖B时,B实例会在第一次初始化请求创建,之后的对A的调用间接依赖的B仍旧是同一实例,这并非B所声明的scope=Prototype含义。
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
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;
}
}
上述createCommand方法里调用了getBean方法改变了依赖注入方式。但是还有一点“瑕疵”:依赖了ApplicationContext。这种任务Spring也提供了,因为诞生初衷就是为了减少代码的耦合程度,所以有了后来的控制反转。Look up method解决了这个问题。只要对每个要使用getBean代码的方法配置一个Bean(不支持一个方法对应多个Bean),注意替换的方法是无参的<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
<!-- inject dependencies here as required -->
</bean>
<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
<lookup-method name="createCommand" bean="command"/>
</bean>
现在代码不再依赖于Springpackage fiona.apple;
// 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();
}
很少使用但很强大的同宗replace method
lookup method只是替换了getBean这样的简单代码,而replace method它将深入到指定bean之后的方法调用中,即MethodReplacer的方法reimplement,这里可以做更多的事,显然它支持并且一定比较可能重载的方法。
/** 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 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"/>
实现
之前提到过AbstractBeanFactory,其子类AbstractAutowireCapableBeanFactory实现了instantiateBean方法
再进入SimpleInstantiationStrategy,可以看到如果有方法覆盖将调用instantiateWithMethodInjection,否则使用反射机制实例化public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (beanDefinition.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (beanDefinition.constructorArgumentLock) {
constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class clazz = beanDefinition.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {
public Constructor run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(beanDefinition, beanName, owner);
}
}
SimpleInstantiationStrategy子类CglibSubclassingInstantiationStrategy实现了instantiateWithMethodInjection方法,显然method注入的两种方式都是使用Cglib实现的。
setSuperclass:设置要代理的父类
setCallbackFilter:设置过滤器,有一个accept方法返回拦截器的索引值:
lookup method 该方法使用lookup method
replace method 改方法使用replace method
not found 不对方法拦截
setCallbacks:设置拦截器public Object instantiate(Constructor ctor, Object[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.beanDefinition.getBeanClass());
enhancer.setCallbackFilter(new CallbackFilterImpl());
enhancer.setCallbacks(new Callback[] {
NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(),
new ReplaceOverrideMethodInterceptor()
});
return (ctor == null) ?
enhancer.create() :
enhancer.create(ctor.getParameterTypes(), args);
}
lookup method拦截private class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
// Cast is safe, as CallbackFilter filters are used selectively.
LookupOverride lo = (LookupOverride) beanDefinition.getMethodOverrides().getOverride(method);
return owner.getBean(lo.getBeanName());
}
}
replace method拦截private class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
ReplaceOverride ro = (ReplaceOverride) beanDefinition.getMethodOverrides().getOverride(method);
// TODO could cache if a singleton for minor performance optimization
MethodReplacer mr = (MethodReplacer) owner.getBean(ro.getMethodReplacerBeanName());
return mr.reimplement(obj, method, args);
}
}
- 大小: 6.3 KB
- 大小: 54.4 KB
分享到:
相关推荐
本文实例讲述了Jquery动态替换div内容及动态展示的方法。分享给大家供大家参考。具体分析如下: 一、问题: 项目中需要在后台拼接html然后在前台通过ajax展示到div中: 复制代码 代码如下:sys_ajaxGet(“/dynamic/...
主要介绍了Java Method类及invoke方法原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
Index The CreateRemoteThread method The SetWindowsHookEx method The code cave method Appendix A - Methods of obtaining a process ID Appendix B - Methods of obtaining a thread ID ...
Simple sensorless algorithm for interior permanent magnet synchronous motors based on high-frequency voltage injection method
C++设计模式课件8_Factory Method_工厂方法.pdf
Flicker_量测原理及应用.pdf,液晶面板Flicker量测,计算方法,包含Flicker Measurement by Contrast Method,Flicker Measurement by JEITA Method,Flicker Measurement by VESA Method
模板方法模式是一种行为设计模式,它在一个方法中定义算法的骨架,将一些步骤延迟到子类中实现。 具体来说,模板方法模式的关键特点包括: 抽象类:在抽象类中定义一个模板方法,该方法给出了算法的框架。 具体...
反射之操作 Method 成员方法类.md
struts动态访问调用之一,采用method属性,同一个Action内的不同方法来响应用户请求
给出了三种动态子结构方法的程序,对比了自由界面模态综合法,固定界面模态综合法,双协调自由界面模态综合法三种方法。-Shows three dynamic substructure method of procedure, compared to the free interface ...
The cooling system of an injection mould is very important to the productivity of the injection moulding process and the quality of the moulded part. Despite the various research efforts that have ...
FACTORY METHOD(工厂方法)
This paper presents a simplified HF injection method for permanent magnet synchronous motor (PMSM) sensorless control. The discussed HF injection scheme utilizes motor magnetic saliency property which...
本文实例讲述了Python面向对象程序设计之静态方法、类方法、属性方法原理与用法。分享给大家供大家参考,具体如下: 前言:认为方法与函数同意义,由于这里使用method,所以称为方法 静态方法: 使用@staticmethod...
参看 Dave Shea’s excellent summary ,Paul Young 在分析现存的所有方法的优缺点之后,提出了一种新的方法,并将其命名为“状态域方法”(The State Method),本文将详细介绍该方法的原理: 现存方法的缺点: ...
SystemC用Method方法实现交通灯控制
template-method-demo 模板方法示例
METHOD
基于无网格方法的微注射成型数值模拟,石凡,张响,本论文主要讨论了基于无网格SPH(Smoothed Particle Hydrodynamics)方法的微注射成型模拟程序MIS(Mesh Free Micro Injection Moulding Simulation Code)的模拟能�