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

原创
2017/01/12 14:23
阅读数 2.8K

策略流程

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<?> enhancedSubclassConstructor = 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方法。

展开阅读全文
打赏
1
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
1
分享
返回顶部
顶部