Spring源码阅读-实例化策略InstantiationStrategy
2017-01-12 00:00
489 查看
摘要: 实例化策略中包括两种情况:反射,cglib
在SimpleInstantiationStrategy中对这三个方法做了简单实现,如果工厂方法实例化直接用反射创建对象,如果是构造方法实例化的则判断是否有MethodOverrides,如果有无MethodOverrides也是直接用反射,如果有MethodOverrides就需要用cglib实例化对象,SimpleInstantiationStrategy把通过cglib实例化的任务交给了它的子类CglibSubclassingInstantiationStrategy。
类BeanDefinitionParserDelegate在解析bean标签的时候 发现了下面两个方法:
方法parseLookupOverrideSubElements解析标签lookup-method,
方法parseReplacedMethodSubElements解析标签replaced-method
这两个标签是配置在bean标签的下一级,并且replaced-method还有自己的子标签
看CglibSubclassCreator:
以instantiate为入口通过cglib的Enhancer生成subClass, 这里生成subClass的时候传人了原始class和Callback,并通过MethodOverrideCallbackFilter里面定义调用callback类型:
这里的PASSTHROUGH,LOOKUP_OVERRIDE,METHOD_REPLACER常量值和所有调用Callbak数组下标对应,分别是LOOKUP_OVERRIDE对应着LookupOverrideMethodInterceptor,METHOD_REPLACER对应着ReplaceOverrideMethodInterceptor,分别看这两种callback业务:
LookupOverrideMethodInterceptor:
ReplaceOverrideMethodInterceptor
策略流程
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方法。
相关文章推荐
- Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)
- Spring源码阅读入门指引
- 设计模式--spring源码中使用策略模式(Strategy Pattern)
- spring-mvc源码阅读(一)servlet
- Spring源码阅读——获得bean
- Spring源码阅读——BeanFactory体系结构
- spring源码下载及与myeclipse集成阅读
- Spring源码阅读入门指引
- Spring 源码阅读(二)——Spring的初始化以及资源加载
- Spring 源码阅读(1)
- Spring 源码阅读笔记(一)
- Spring 源码阅读之BeanFactory
- Spring源码阅读之IoC容器初始化1 -- Resource定位
- [Spring3.x源码]AOP(三)代理类的实例化
- Spring源码阅读3
- 初始化IoC容器(Spring源码阅读)
- Spring源码解析:Bean的实例化与依赖注入(四)
- Spring IOC 源码阅读资源加载和注册
- Spring源码阅读之IoC容器初始化3 -- BeanDefinition在IoC容器中的注册
- spring-mvc源码阅读(三)RequestMappingHandlerMapping