Spring源码分析-初识ProxyFactoryBean(五)

来源:互联网 发布:js实现360度全景 编辑:程序博客网 时间:2024/06/04 18:43

这一节我们进入Spring的AOP功能的源码解析。

一:首先我们来看一下ProxyFactoryBean的继承层次

Object

----ProxyConfig

    ----AdvisedSupport

          ----ProxyCreatorSupport

                ----ProxyFactoryBean

在这里,ProxyConfig是一个数据类,这个数据基类为像ProxyFactoryBean这样的子类提供了配置属性。

                AdvisedSupport封装了AOP中对通知和通知器的相关操作。

                ProxyCreatorSupport是子类创建AOP代理对象的一个辅助类


二:ProxyFactoryBean的getObject


/** * Return a proxy. Invoked when clients obtain beans from this factory bean. * Create an instance of the AOP proxy to be returned by this factory. * The instance will be cached for a singleton, and create on each call to * <code>getObject()</code> for a proxy. * @return a fresh AOP proxy reflecting the current state of this factory */public Object getObject() throws BeansException {initializeAdvisorChain();if (isSingleton()) {return getSingletonInstance();}else {if (this.targetName == null) {logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +"Enable prototype proxies by setting the 'targetName' property.");}return newPrototypeInstance();}}
为Proxy代理对象配置Advisor链是在initializeAdvisorChain方法中实现的。

我们来看看initializeAdvisorChain的源码实现:

/** * Create the advisor (interceptor) chain. Aadvisors that are sourced * from a BeanFactory will be refreshed each time a new prototype instance * is added. Interceptors added programmatically through the factory API * are unaffected by such changes. */private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {if (this.advisorChainInitialized) {return;}if (!ObjectUtils.isEmpty(this.interceptorNames)) {if (this.beanFactory == null) {throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));}// Globals can't be last unless we specified a targetSource using the property...if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {throw new AopConfigException("Target required after globals");}// Materialize interceptor chain from bean names.for (int i = 0; i < this.interceptorNames.length; i++) {String name = this.interceptorNames[i];if (logger.isTraceEnabled()) {logger.trace("Configuring advisor or advice '" + name + "'");}if (name.endsWith(GLOBAL_SUFFIX)) {if (!(this.beanFactory instanceof ListableBeanFactory)) {throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");}addGlobalAdvisor((ListableBeanFactory) this.beanFactory,name.substring(0, name.length() - GLOBAL_SUFFIX.length()));}else {// If we get here, we need to add a named interceptor.// We must check if it's a singleton or prototype.Object advice = null;if (this.singleton || this.beanFactory.isSingleton(this.interceptorNames[i])) {// Add the real Advisor/Advice to the chain.advice = this.beanFactory.getBean(this.interceptorNames[i]);}else {// It's a prototype Advice or Advisor: replace with a prototype.// Avoid unnecessary creation of prototype bean just for advisor chain initialization.advice = new PrototypePlaceholderAdvisor(this.interceptorNames[i]);}addAdvisorOnChainCreation(advice, this.interceptorNames[i]);}}}this.advisorChainInitialized = true;}

在这个方法中,最核心的操作是addGlobalAdvisor和addAdvisorOnChainCreation,我们来看一下addAdvisorOnChainCreation的源码

/** * Invoked when advice chain is created. * <p>Add the given advice, advisor or object to the interceptor list. * Because of these three possibilities, we can't type the signature * more strongly. * @param next advice, advisor or target object * @param name bean name from which we obtained this object in our owning * bean factory */private void addAdvisorOnChainCreation(Object next, String name) {// We need to convert to an Advisor if necessary so that our source reference// matches what we find from superclass interceptors.Advisor advisor = namedBeanToAdvisor(next);if (logger.isTraceEnabled()) {logger.trace("Adding advisor with name '" + name + "'");}addAdvisor((Advisor) advisor);}

在这里addAdvisor实际上是在父类AdvisorSupport里实现的,是把实例化的Advisor加入到AdvisorSupport的实例变量advisors(LinkedList)中。

现在我们回到ProxyFactoryBean的getObject中,来看一下getSingletonInstance的源码实现。

/** * Return the singleton instance of this class's proxy object, * lazily creating it if it hasn't been created already. * @return the shared singleton proxy */private synchronized Object getSingletonInstance() {if (this.singletonInstance == null) {this.targetSource = freshTargetSource();if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {// Rely on AOP infrastructure to tell us what interfaces to proxy.Class targetClass = getTargetClass();if (targetClass == null) {throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");}setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));}// Initialize the shared singleton instance.super.setFrozen(this.freezeProxy);this.singletonInstance = getProxy(createAopProxy());}return this.singletonInstance;}

我们可以看到属性singletonInstance用来缓存这个单件对象,具体的获取是通过getProxy(createAopProxy())方法来完成的。

/** * Return the proxy object to expose. * <p>The default implementation uses a <code>getProxy</code> call with * the factory's bean class loader. Can be overridden to specify a * custom class loader. * @param aopProxy the prepared AopProxy instance to get the proxy from * @return the proxy object to expose * @see AopProxy#getProxy(ClassLoader) */protected Object getProxy(AopProxy aopProxy) {return aopProxy.getProxy(this.proxyClassLoader);}

我们首先来看一下createAopProxy方法的源码,这个方法是在父类ProxyCreatorSupport中实现的。

/** * Subclasses should call this to get a new AOP proxy. They should <b>not</b> * create an AOP proxy with <code>this</code> as an argument. */protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}return getAopProxyFactory().createAopProxy(this);}

getAopProxyFactory()方法返回的DefaultAopProxyFactory,我们来看看DefaultAopProxyFactory是如何createAopProxy的。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}if (targetClass.isInterface()) {return new JdkDynamicAopProxy(config);}if (!cglibAvailable) {throw new AopConfigException("Cannot proxy target class because CGLIB2 is not available. " +"Add CGLIB to the class path or specify proxy interfaces.");}return CglibProxyFactory.createCglibProxy(config);}else {return new JdkDynamicAopProxy(config);}}
根据源码我们可以看出DefaultAopProxyFactory根据不同的需要生成JdkDynamicAopProxy或者Cglib2AopProxy.现在我们来看看JdkDynamicAopProxy是怎样完成AopProxy代理对象生成工作的。

JdkDynamicAopProxy生成Proxy代理对象源码:

public Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());}Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}

重点关注Proxy.newProxyInstance这个代理方法,通过this我们知道JdkDynamicAopProxy implements InvocationHandler,对于invoke方法的源码留待下一节讲解。

我们现来看一下Cglib2AopProxy是如何getProxy的。


public Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource());}try {Class rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class proxySuperClass = rootClass;if (AopUtils.isCglibProxyClass(rootClass)) {proxySuperClass = rootClass.getSuperclass();Class[] additionalInterfaces = rootClass.getInterfaces();for (int i = 0; i < additionalInterfaces.length; i++) {Class additionalInterface = additionalInterfaces[i];this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.validateClassIfNecessary(proxySuperClass);// Configure CGLIB Enhancer...Enhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}enhancer.setSuperclass(proxySuperClass);enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setInterceptDuringConstruction(false);Callback[] callbacks = getCallbacks(rootClass);enhancer.setCallbacks(callbacks);enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));Class[] types = new Class[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.Object proxy;if (this.constructorArgs != null) {proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);}else {proxy = enhancer.create();}return proxy;}catch (CodeGenerationException ex) {throw new AopConfigException("Could not generate CGLIB subclass of class [" +this.advised.getTargetClass() + "]: " +"Common causes of this problem include using a final class or a non-visible class",ex);}catch (IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of class [" +this.advised.getTargetClass() + "]: " +"Common causes of this problem include using a final class or a non-visible class",ex);}catch (Exception ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}

我们进入getCallbacks方法来看看是如何生成callback的 
private Callback[] getCallbacks(Class rootClass) throws Exception {// Parameters used for optimisation 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).Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);// Choose a "straight to target" interceptor. (used for calls that are// unadvised but can return this). May be required to expose the proxy.Callback targetInterceptor = null;if (exposeProxy) {targetInterceptor = isStatic ?(Callback) new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :(Callback) new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());}else {targetInterceptor = isStatic ?(Callback) new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :(Callback) new DynamicUnadvisedInterceptor(this.advised.getTargetSource());}// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).Callback targetDispatcher = isStatic ?(Callback) new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();Callback[] mainCallbacks = new Callback[]{aopInterceptor, // for normal advicetargetInterceptor, // invoke target without considering advice, if optimizednew SerializableNoOp(), // no override for methods mapped to thistargetDispatcher, this.advisedDispatcher,new EqualsInterceptor(this.advised),new HashCodeInterceptor(this.advised)};Callback[] callbacks;// If the target is a static one and the advice chain is frozen,// then we can make some optimisations by sending the AOP calls// direct to the target using the fixed chain for that method.if (isStatic && isFrozen) {Method[] methods = rootClass.getMethods();Callback[] fixedCallbacks = new Callback[methods.length];this.fixedInterceptorMap = new HashMap(methods.length);// TODO: small memory optimisation here (can skip creation for// methods with no advice)for (int x = 0; x < methods.length; x++) {List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());this.fixedInterceptorMap.put(methods[x].toString(), new Integer(x));}// Now copy both the callbacks from mainCallbacks// and fixedCallbacks into the callbacks array.callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];for (int x = 0; x < mainCallbacks.length; x++) {callbacks[x] = mainCallbacks[x];}for (int x = 0; x < fixedCallbacks.length; x++) {callbacks[x + mainCallbacks.length] = fixedCallbacks[x];}this.fixedInterceptorOffset = mainCallbacks.length;}else {callbacks = mainCallbacks;}return callbacks;}

最核心的方法同样留到下一节再介绍。

// Choose an "aop" interceptor (used for AOP calls).Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);