您的位置:首页 > 编程语言 > Java开发

Spring源码阅读-实例化策略InstantiationStrategy

2017-01-12 00:00 489 查看
摘要: 实例化策略中包括两种情况:反射,cglib

策略流程

spring中角色分工很明确,创建对象的时候先通过 ConstructorResolver找到对应的实例化方法和参数,再通过实例化策略InstantiationStrategy进行实例化,根据创建对象的三个分支( 工厂方法、有参构造方法、无参构造方法 ), InstantiationStrategy提供了三个接口方法:

public interface InstantiationStrategy {

//默认构造方法
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) throws BeansException;

//指定构造方法
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner, Constructor<?> ctor,
Object[] args) throws BeansException;

//指定工厂方法
Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner, Object factoryBean,
Method factoryMethod, Object[] args) throws BeansException;

}

在SimpleInstantiationStrategy中对这三个方法做了简单实现,如果工厂方法实例化直接用反射创建对象,如果是构造方法实例化的则判断是否有MethodOverrides,如果有无MethodOverrides也是直接用反射,如果有MethodOverrides就需要用cglib实例化对象,SimpleInstantiationStrategy把通过cglib实例化的任务交给了它的子类CglibSubclassingInstantiationStrategy。

MethodOverrides

先看一下MethodOverrides对应的配置是在什么地方,找到解析标签元素的地方,

类BeanDefinitionParserDelegate在解析bean标签的时候 发现了下面两个方法:

方法parseLookupOverrideSubElements解析标签lookup-method,

方法parseReplacedMethodSubElements解析标签replaced-method

这两个标签是配置在bean标签的下一级,并且replaced-method还有自己的子标签

cglib策略

Cglib的实例化策略里是通过它的内部类CglibSubclassCreator来实例化:

protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinition, String beanName,
BeanFactory owner, Constructor<?> ctor, Object[] args) {

// Must generate CGLIB subclass.
return new CglibSubclassCreator(beanDefinition, owner).instantiate(ctor, args);
}

看CglibSubclassCreator:

private static class CglibSubclassCreator {

//这里的数组位置很重要, 后面MethodOverrideCallbackFilter通过指定下标获取对应的拦截
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[] { NoOp.class,
LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class };

private final RootBeanDefinition beanDefinition;

private final BeanFactory owner;

CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
}

//实例化入口:动态构造子类
Object instantiate(Constructor<?> ctor, Object[] args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiate(subclass);
} else {
try {
Constructor<?> enhancedSu
3ff8
bclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
} catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), String.format(
"Failed to invoke constructor for CGLIB enhanced subclass [%s]", subclass.getName()), ex);
}
}
//这个地方解决一个bug,bug提交报告https://jira.spring.io/browse/SPR-10785
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] { NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner) });
return instance;
}

/**
* Create an enhanced subclass of the bean class for the provided bean
* definition, using CGLIB.
*/
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
//cglib里面的用法,对原始class进行增强,并设置callback
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
//过滤,自定义逻辑来指定调用的callback下标(callback会以数组的方式传人)
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
//只是生产class就直接指定callback类型,跟上面CallbackFilter对应
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
}
}

以instantiate为入口通过cglib的Enhancer生成subClass, 这里生成subClass的时候传人了原始class和Callback,并通过MethodOverrideCallbackFilter里面定义调用callback类型:

private static class MethodOverrideCallbackFilter extends CglibIdentitySupport implements CallbackFilter {
//...

@Override
public int accept(Method method) {
//配置文件加载到MethodOverrides集合中
MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method);
if (logger.isTraceEnabled()) {
logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]");
}
if (methodOverride == null) {
return PASSTHROUGH;//0
} else if (methodOverride instanceof LookupOverride) {
return LOOKUP_OVERRIDE;//1
} else if (methodOverride instanceof ReplaceOverride) {
return METHOD_REPLACER;//2
}
throw new UnsupportedOperationException(
"Unexpected MethodOverride subclass: " + methodOverride.getClass().getName());
}
}

这里的PASSTHROUGH,LOOKUP_OVERRIDE,METHOD_REPLACER常量值和所有调用Callbak数组下标对应,分别是LOOKUP_OVERRIDE对应着LookupOverrideMethodInterceptor,METHOD_REPLACER对应着ReplaceOverrideMethodInterceptor,分别看这两种callback业务:

LookupOverrideMethodInterceptor:
private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {

private final BeanFactory owner;

LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
}

@Override
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) getBeanDefinition().getMethodOverrides().getOverride(method);
return this.owner.getBean(lo.getBeanName());
}
}
直接把lookup-method配置的对象返回,这个用于插拔式程序特别方便

ReplaceOverrideMethodInterceptor
private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {

private final BeanFactory owner;

ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
super(beanDefinition);
this.owner = owner;
}

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
// TODO could cache if a singleton for minor performance
// optimization
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
return mr.reimplement(obj, method, args);
}
}
通过methodReplacerBeanName获取替换对象,该对象实现了MethodReplacer接口,获取到该对象后调用reimplement方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息