源码分析一下spring的scoped-proxy(二)

1,427 阅读4分钟

文章开始

上篇文章,介绍了spring使用装饰器解决singleton依赖prototype的问题,最终spring再创建singleton实例的时候,实际上为该singleton生成了一个代理ScopedProxyFactoryBean的代理对象,今天我们看看ScopedProxyFactoryBean生成代理对象的源码。

ScopedProxyFactoryBeansetBeanFactory时会实例化好代理对象

先贴代码

 /**继承自ProxyConfig代理配置类,
实现了BeanFactoryAware接口(spring获取该对象实例时会调用该接口的getObject()),
*实现了shiBeanFactoryAware,spring注入当前的beanFactory对象
*
*/
public class ScopedProxyFactoryBean extends ProxyConfig
        implements FactoryBean<Object>, BeanFactoryAware, AopInfrastructureBean {

    /** The TargetSource that manages scoping. */
    //定义一个新的SimpleBeanTargetSource对象,该对象包含beanFactory和targetBeanName对象。
    //实际上代理在调用MyTestBean的任意方法时,会从该对象的的beanFactory中重新获取targetBeanName的对象,即我们的scope为prototype的MyTestBean实例。这样就保证了每一次使用时都是一个新的MyTestBean实例
    private final SimpleBeanTargetSource scopedTargetSource = new SimpleBeanTargetSource();

    /** The name of the target bean. */
    @Nullable
    //再注册该bean声明时,添加了该属性的值,这里为“scopedTarget.myTestBean”
    private String targetBeanName;

    /** The cached singleton proxy. */
    @Nullable
    //最终的生成的代理对象
    private Object proxy;


    /**
     * Create a new ScopedProxyFactoryBean instance.
     */
    public ScopedProxyFactoryBean() {
        setProxyTargetClass(true);
    }


    /**
     * Set the name of the bean that is to be scoped.
     */
     //注入targetBeanName,这里为“scopedTarget.myTestBean”
    public void setTargetBeanName(String targetBeanName) {
        this.targetBeanName = targetBeanName;
        this.scopedTargetSource.setTargetBeanName(targetBeanName);
    }
    
    
    @Override
    //实现了BeanFactoryAware接口,spring会将beanFactory注入进来
    public void setBeanFactory(BeanFactory beanFactory) {
        if (!(beanFactory instanceof ConfigurableBeanFactory)) {
            throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
        }
        ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
        
        //scopedTargetSource注入beanFactory
        this.scopedTargetSource.setBeanFactory(beanFactory);
        //新建一个代理工厂
        ProxyFactory pf = new ProxyFactory();
        pf.copyFrom(this);
        //代理工厂设置初始化好的目标对象
        pf.setTargetSource(this.scopedTargetSource);

        Assert.notNull(this.targetBeanName, "Property 'targetBeanName' is required");
        Class<?> beanType = beanFactory.getType(this.targetBeanName);
        if (beanType == null) {
            throw new IllegalStateException("Cannot create scoped proxy for bean '" + this.targetBeanName +
                    "': Target type could not be determined at the time of proxy creation.");
        }
        if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {
            pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));
        }

        // Add an introduction that implements only the methods on ScopedObject.
        ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());
        //代理工厂设置Advice通知
        pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));

        // Add the AopInfrastructureBean marker to indicate that the scoped proxy
        // itself is not subject to auto-proxying! Only its target bean is.
        //添加接口
        pf.addInterface(AopInfrastructureBean.class);
        //生成代理对象
        this.proxy = pf.getProxy(cbf.getBeanClassLoader());
    }


    @Override
    //实现了FactoryBean接口,spring获取该对象实例时会调用该接口的getObject()
    //这里将代理对象proxy对象返回
    public Object getObject() {
        if (this.proxy == null) {
            throw new FactoryBeanNotInitializedException();
        }
        return this.proxy;
    }

    @Override
    public Class<?> getObjectType() {
        if (this.proxy != null) {
            return this.proxy.getClass();
        }
        return this.scopedTargetSource.getTargetClass();
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

}

ScopedProxyFactoryBean 生成代理对象时new了一个ProxyFactory对象,再对该对象进行属性以及目标对象的一些设置。 (这里利用了spring的BeanFactoryAware接口,获取ScopedProxyFactoryBean的实例时spring实例时会调用setBeanFactory()方法)

其中有两行代码需要先关注下

	//代理工厂设置初始化好的目标对象
   pf.setTargetSource(this.scopedTargetSource);
   ...
   //代理工厂设置Advice通知
   pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));

使用CGlib生成动态代理对象

我们再追一下this.proxy = pf.getProxy(cbf.getBeanClassLoader())方法,由于我们这里的myTestBean并没有实现接口,这里spring会自动使用Cglib生成代理

@Override
   public Object getProxy(@Nullable ClassLoader classLoader) {
   	...
   	try {
   		Class<?> rootClass = this.advised.getTargetClass();
   		...
   		// Configure CGLIB Enhancer...
   		Enhancer enhancer = createEnhancer();
   		...
   		enhancer.setSuperclass(proxySuperClass);
   		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
   		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
   		enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
   		//生成相关的方法回调
   		Callback[] callbacks = getCallbacks(rootClass);
   		Class<?>[] types = new Class<?>[callbacks.length];
   		for (int x = 0; x < types.length; x++) {
   			types[x] = callbacks[x].getClass();
   		}
   		// fixedInterceptorMap only populated at this point, after getCallbacks call above
   		enhancer.setCallbackFilter(new ProxyCallbackFilter(
   				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
   		enhancer.setCallbackTypes(types);

   		// Generate the proxy class and create a proxy instance.
   		return createProxyClassAndInstance(enhancer, callbacks);
   	}
   	catch (CodeGenerationException | IllegalArgumentException ex) {
   		throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
   				": Common causes of this problem include using a final class or a non-visible class",
   				ex);
   	}
   	catch (Throwable ex) {
   		// TargetSource.getTarget() failed
   		throw new AopConfigException("Unexpected AOP exception", ex);
   	}
   }

如果熟悉Cglib的同学,对于Enhancer类应该并不陌生,这里不再赘述,也可查看代理模式和动态代理, Cglib重要的就是回调函数的获取,我们再来看一看这一行重要的代码

			Callback[] callbacks = getCallbacks(rootClass);
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
   	// Parameters used for optimization choices...
   	boolean exposeProxy = this.advised.isExposeProxy();
   	boolean isFrozen = this.advised.isFrozen();
   	boolean isStatic = this.advised.getTargetSource().isStatic();

   	// Choose an "aop" interceptor (used for AOP calls).
       
       //将advised对象(这里其实就是我们的ProxyFactory对象)构造器注入,生成一个DynamicAdvisedInterceptor方法拦截器
   	Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
       ....
}

我们再查看该DynamicAdvisedInterceptor的intercept方法

@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
            //目标资源类
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
                //从目标资源来内来获取目标对象
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);			 
                
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

重点代码在这里:

	//目标资源类
	TargetSource targetSource = this.advised.getTargetSource();
    ...
    //从目标资源类里面获取目标对象
    target = targetSource.getTarget();
    ...
    利用反射执行目标方法。

advised对象其实就是我们文章开头说的ScopedProxyFactoryBean对象 setBeanFactory时new 的 BeanFactory对象,该bf对象的scopedTargetSource属性中targetNamebeanFactory都已经设置过了。 此时我们再调用getTarget()方法获取目标对象时,相当于从当前BeanFactory再获取一次名为targetName的实例,我们这里名为‘scopedTarget.myTestBean’。由于该实例是prototype的, 所以每次调用方法时,相当于从spring容器中重新获取一个'Scoped'目标对象,然后由目标对象执行目标方法。

先简单写点ε=(´ο`*)))