# 源码解析:AOP(2)

接上篇# 源码解析:AOP

cglib类代理

使用cglib实现的代理与jdk代理类似,只是代理对象的构造方式不同。

public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating CGLIB proxy: " + 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;
      // 如果目标类已是cglib生成的代理类,那么继续向上查找
      if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
         proxySuperClass = rootClass.getSuperclass();
         Class<?>[] additionalInterfaces = rootClass.getInterfaces();
         for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
         }
      }

      // Validate the class, writing log messages as necessary.
      // 验证方法,如果存在无法继承的方法,如final,static,打印日志信息
      validateClassIfNecessary(proxySuperClass, classLoader);

      // 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.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      // 使用入参给定的类加载器加载类,如果不为空
      enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(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);
   }
}

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
   enhancer.setInterceptDuringConstruction(false);
   enhancer.setCallbacks(callbacks);
   return (this.constructorArgs != null && this.constructorArgTypes != null ?
         enhancer.create(this.constructorArgTypes, this.constructorArgs) :
         enhancer.create());
}

Spring使用ObjenesisCglibAopProxy拓展了CglibAopProxy,并从4.0开始作为默认选项。它覆写了CglibAopProxycreateProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)方法,使用Objenesis创建cglib代理对象。

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
   Class<?> proxyClass = enhancer.createClass();
   Object proxyInstance = null;

   // 默认为true,可以指定spring.objenesis.ignore为true使其返回false
   if (objenesis.isWorthTrying()) {
      try {
         proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
      }
      catch (Throwable ex) {
         logger.debug("Unable to instantiate proxy using Objenesis, " +
               "falling back to regular proxy construction", ex);
      }
   }

   if (proxyInstance == null) {
      // Regular instantiation via default constructor...
      try {
         Constructor<?> ctor = (this.constructorArgs != null ?
               proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
               proxyClass.getDeclaredConstructor());
         ReflectionUtils.makeAccessible(ctor);
         proxyInstance = (this.constructorArgs != null ?
               ctor.newInstance(this.constructorArgs) : ctor.newInstance());
      }
      catch (Throwable ex) {
         throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
               "and regular proxy instantiation via default constructor fails as well", ex);
      }
   }

   ((Factory) proxyInstance).setCallbacks(callbacks);
   return proxyInstance;
}

createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)方法中较为重要的部分是getCallbacks方法的调用,此方法的作用是获取方法拦截器,以增强对应的方法。

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
   // Parameters used for optimization choices...
   boolean exposeProxy = this.advised.isExposeProxy();
   // 默认为false
   boolean isFrozen = this.advised.isFrozen();
   // 一般为true
   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;
   if (exposeProxy) {
      targetInterceptor = (isStatic ?
            new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
   }
   else {
      targetInterceptor = (isStatic ?
            new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
            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 ?
         new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

   Callback[] mainCallbacks = new Callback[] {
         aopInterceptor,  // for normal advice
         targetInterceptor,  // invoke target without considering advice, if optimized
         new SerializableNoOp(),  // no override for methods mapped to this
         targetDispatcher, 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 optimizations 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 optimization here (can skip creation for methods with no advice)
      for (int x = 0; x < methods.length; x++) {
         Method method = methods[x];
         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
         fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
               chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
         this.fixedInterceptorMap.put(method, x);
      }

      // Now copy both the callbacks from mainCallbacks
      // and fixedCallbacks into the callbacks array.
      callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
      System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
      System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
      this.fixedInterceptorOffset = mainCallbacks.length;
   }
   else {
      callbacks = mainCallbacks;
   }
   return callbacks;
}

其中主要的callbacks如下:

Callback[] mainCallbacks = new Callback[] {
    aopInterceptor,  // for normal advice
    targetInterceptor,  // invoke target without considering advice, if optimized
    new SerializableNoOp(),  // no override for methods mapped to this
    targetDispatcher, this.advisedDispatcher,
    new EqualsInterceptor(this.advised),
    new HashCodeInterceptor(this.advised)
};

aopInterceptor用于获取拦截器链,然后进行组合并调用。

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);
      }
   }
}

targetInterceptor用于没有advice的情况,根据静动态和exposeProxy分为四种,下面是静态的两种:

private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {

   @Nullable
   private final Object target;

   public StaticUnadvisedInterceptor(@Nullable Object target) {
      this.target = target;
   }

   @Override
   @Nullable
   public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
      Object retVal = methodProxy.invoke(this.target, args);
      return processReturnType(proxy, this.target, method, retVal);
   }
}


private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {

   @Nullable
   private final Object target;

   public StaticUnadvisedExposedInterceptor(@Nullable Object target) {
      this.target = target;
   }

   @Override
   @Nullable
   public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
      Object oldProxy = null;
      try {
         oldProxy = AopContext.setCurrentProxy(proxy);
         Object retVal = methodProxy.invoke(this.target, args);
         return processReturnType(proxy, this.target, method, retVal);
      }
      finally {
         AopContext.setCurrentProxy(oldProxy);
      }
   }
}

其他类型的callback不多描述,具体调用哪一个callback由ProxyCallbackFilter决定:

public int accept(Method method) {
   if (AopUtils.isFinalizeMethod(method)) {
      logger.trace("Found finalize() method - using NO_OVERRIDE");
      return NO_OVERRIDE;
   }
   if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
         method.getDeclaringClass().isAssignableFrom(Advised.class)) {
      if (logger.isTraceEnabled()) {
         logger.trace("Method is declared on Advised interface: " + method);
      }
      return DISPATCH_ADVISED;
   }
   // We must always proxy equals, to direct calls to this.
   if (AopUtils.isEqualsMethod(method)) {
      if (logger.isTraceEnabled()) {
         logger.trace("Found 'equals' method: " + method);
      }
      return INVOKE_EQUALS;
   }
   // We must always calculate hashCode based on the proxy.
   if (AopUtils.isHashCodeMethod(method)) {
      if (logger.isTraceEnabled()) {
         logger.trace("Found 'hashCode' method: " + method);
      }
      return INVOKE_HASHCODE;
   }
   Class<?> targetClass = this.advised.getTargetClass();
   // Proxy is not yet available, but that shouldn't matter.
   List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
   boolean haveAdvice = !chain.isEmpty();
   boolean exposeProxy = this.advised.isExposeProxy();
   boolean isStatic = this.advised.getTargetSource().isStatic();
   boolean isFrozen = this.advised.isFrozen();
   if (haveAdvice || !isFrozen) {
      // If exposing the proxy, then AOP_PROXY must be used.
      if (exposeProxy) {
         if (logger.isTraceEnabled()) {
            logger.trace("Must expose proxy on advised method: " + method);
         }
         return AOP_PROXY;
      }
      Method key = method;
      // Check to see if we have fixed interceptor to serve this method.
      // Else use the AOP_PROXY.
      if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
         if (logger.isTraceEnabled()) {
            logger.trace("Method has advice and optimizations are enabled: " + method);
         }
         // We know that we are optimizing so we can use the FixedStaticChainInterceptors.
         int index = this.fixedInterceptorMap.get(key);
         return (index + this.fixedInterceptorOffset);
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Unable to apply any optimizations to advised method: " + method);
         }
         return AOP_PROXY;
      }
   }
   else {
      // See if the return type of the method is outside the class hierarchy of the target type.
      // If so we know it never needs to have return type massage and can use a dispatcher.
      // If the proxy is being exposed, then must use the interceptor the correct one is already
      // configured. If the target is not static, then we cannot use a dispatcher because the
      // target needs to be explicitly released after the invocation.
      if (exposeProxy || !isStatic) {
         return INVOKE_TARGET;
      }
      Class<?> returnType = method.getReturnType();
      if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
         if (logger.isTraceEnabled()) {
            logger.trace("Method return type is assignable from target type and " +
                  "may therefore return 'this' - using INVOKE_TARGET: " + method);
         }
         return INVOKE_TARGET;
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Method return type ensures 'this' cannot be returned - " +
                  "using DISPATCH_TARGET: " + method);
         }
         return DISPATCH_TARGET;
      }
   }
}

cglib代理还提供了一个优化机制,如果isFrozen为true,那么将创建一个固定的拦截链FixedChainStaticTargetInterceptor,因为此时无法调用Advised接口的方法增加或者删除Advise或者Advice,拦截链不会发生改变,因此之后调用方法时将不会每次都进行拦截链的获取。当然,之前在分析jdk代理时发现Spring也对拦截链进行了缓存,不过如果调用了Advised接口中的增加删除方法,那么此缓存将会被移除,下一次调用将会重新获取拦截链。

if (isStatic && isFrozen) {
   Method[] methods = rootClass.getMethods();
   Callback[] fixedCallbacks = new Callback[methods.length];
   this.fixedInterceptorMap = new HashMap<>(methods.length);

   // TODO: small memory optimization here (can skip creation for methods with no advice)
   for (int x = 0; x < methods.length; x++) {
      Method method = methods[x];
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
      fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
            chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
      this.fixedInterceptorMap.put(method, x);
   }

   // Now copy both the callbacks from mainCallbacks
   // and fixedCallbacks into the callbacks array.
   callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
   System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
   System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
   this.fixedInterceptorOffset = mainCallbacks.length;
}

ProxyFactoryBean

Spring还提供了一种基于FactoryBean的方式创建代理对象,即ProxyFactoryBean。它对poincut以及其所应用的advisor, advice等等提供了完全的控制。同时,如果你不需要这些特性,它也提供了最简单的配置方式,例如:

<bean id="personTarget" class="com.mycompany.PersonImpl">
    <property name="name" value="Tony"/>
    <property name="age" value="51"/>
</bean>

<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
    <property name="someProperty" value="Custom string property value"/>
</bean>

<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
</bean>

<bean id="person"
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces" value="com.mycompany.Person"/>

    <property name="target" ref="personTarget"/>
    <property name="interceptorNames">
        <list>
            <value>myAdvisor</value>
            <value>debugInterceptor</value>
        </list>
    </property>
</bean>

你只需要提供target,即需要被代理的目标对象以及interceptorNames,即用于增强的advisor, advice等即可。

下面先介绍一下它的各种属性,与之前分析提到的类似:

  • proxyTargetClass: 代理类或者代理接口
  • optimize: 通过cglib创建代理时是否进行激进的优化,如果不没有完全理解此优化是如何处理的,那么不要使用它。这个属性只对cglib起作用,对jdk代理不起作用。
  • frozen: 如果设置为true,那么创建代理对象后无法改变拦截链。
  • exposeProxy: 决定当前代理对象是否能够通过AopContext.currentProxy()暴露给目标对象。
  • proxyInterfaces: 需要代理的接口。如果不提供,spring会自己查找是否存在可用接口,如果没有则使用cglib代理。
  • interceptorNames: 需要应用到此代理的Advisor, Advice等的bean名称。可以使用通配符*,表示应用所有Advisor, Advice等;也可以使用xxx*,应用名称前缀为xxx的所有Advisor, Advice
  • singleton: 是否只返回一个唯一对象,无论getObject()被调用多少次,默认为true

了解了它的属性后,让我们看一下它的核心方法getObject()

public Object getObject() throws BeansException {
   // 初始化拦截链
   initializeAdvisorChain();
   // 创建单例或者原型
   if (isSingleton()) {
      return getSingletonInstance();
   }
   else {
      if (this.targetName == null) {
         logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
               "Enable prototype proxies by setting the 'targetName' property.");
      }
      return newPrototypeInstance();
   }
}

此方法共分为两步:

  1. 初始化拦截器链。根据interceptorNames获取所有匹配的Advisor
  2. 根据singleton属性,创建单例或者原型代理对象。
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
   if (this.advisorChainInitialized) {
      return;
   }

   // 如果指定了interceptorNames属性
   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 (String name : this.interceptorNames) {
         if (logger.isTraceEnabled()) {
            logger.trace("Configuring advisor or advice '" + name + "'");
         }

         // 如果为xxx*的形式,则增加所有匹配的Advisor
         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;
            if (this.singleton || this.beanFactory.isSingleton(name)) {
               // Add the real Advisor/Advice to the chain.
               advice = this.beanFactory.getBean(name);
            }
            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(name);
            }
            addAdvisorOnChainCreation(advice, name);
         }
      }
   }

   this.advisorChainInitialized = true;
}

initializeAdvisorChain()方法只会被调用一次,从BeanFactory中获取Advisor。如果拦截器名后缀为*,那么将会进行通配符匹配。

private void addGlobalAdvisor(ListableBeanFactory beanFactory, String prefix) {
   // 获取所有Advisor对象
   String[] globalAdvisorNames =
         BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Advisor.class);
   // 获取所有Interceptor对象,它是Advice的子接口
   String[] globalInterceptorNames =
         BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Interceptor.class);
   List<Object> beans = new ArrayList<>(globalAdvisorNames.length + globalInterceptorNames.length);
   Map<Object, String> names = new HashMap<>(beans.size());
   for (String name : globalAdvisorNames) {
      Object bean = beanFactory.getBean(name);
      beans.add(bean);
      names.put(bean, name);
   }
   for (String name : globalInterceptorNames) {
      Object bean = beanFactory.getBean(name);
      beans.add(bean);
      names.put(bean, name);
   }
   // 排序
   AnnotationAwareOrderComparator.sort(beans);
   // 获取匹配的Advisor并增加到拦截器链中
   for (Object bean : beans) {
      String name = names.get(bean);
      if (name.startsWith(prefix)) {
         addAdvisorOnChainCreation(bean, name);
      }
   }
}

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);
}

public void addAdvisor(Advisor advisor) {
   int pos = this.advisors.size();
   addAdvisor(pos, advisor);
}

@Override
public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
   if (advisor instanceof IntroductionAdvisor) {
      validateIntroductionAdvisor((IntroductionAdvisor) advisor);
   }
   addAdvisorInternal(pos, advisor);
}

private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
   Assert.notNull(advisor, "Advisor must not be null");
   if (isFrozen()) {
      throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
   }
   if (pos > this.advisors.size()) {
      throw new IllegalArgumentException(
            "Illegal position " + pos + " in advisor list with size " + this.advisors.size());
   }
   this.advisors.add(pos, advisor);
   updateAdvisorArray();
   adviceChanged();
}

否则,进行常规的bean获取调用。此处对prototype类型的Advisor进行了一点特殊处理(同时ProxyFactoryBeansingletion属性也需要为false),即只进行占位,并不直接实例化它。

advice = new PrototypePlaceholderAdvisor(name);

public PrototypePlaceholderAdvisor(String beanName) {
   this.beanName = beanName;
   this.message = "Placeholder for prototype Advisor/Advice with bean name '" + beanName + "'";
}

单例

单例对象只创建一次,创建完成后将被缓存,之后每次调用都返回此对象。

private synchronized Object getSingletonInstance() {
   if (this.singletonInstance == null) {
      // 获取TargetSource
      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;
}

获取TargetSource分两种情况,第一种情况也是最常见的情况为指定了target属性,此时Spring将会从容器中获取此bean并将它包装为TargetSource对象(默认为SingletonTargetSource),当然,如果这个bean已经是TargetSource对象,那么只需要执行转换即可。第二种情况则是指定了targetSource属性,此时可以直接返回此对象。通过第二种方式,你可以自定义需要的TargetSource或者使用Spring提供的几个TargetSource(比如common,threadlocal等),以达成相应的需求。

private TargetSource freshTargetSource() {
   if (this.targetName == null) {
      if (logger.isTraceEnabled()) {
         logger.trace("Not refreshing target: Bean name not specified in 'interceptorNames'.");
      }
      return this.targetSource;
   }
   else {
      if (this.beanFactory == null) {
         throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
               "- cannot resolve target with name '" + this.targetName + "'");
      }
      if (logger.isDebugEnabled()) {
         logger.debug("Refreshing target with name '" + this.targetName + "'");
      }
      Object target = this.beanFactory.getBean(this.targetName);
      return (target instanceof TargetSource ? (TargetSource) target : new SingletonTargetSource(target));
   }
}

接下来,如果你没有设置proxyInterfaces属性,那么Spring将会自动检查目标对象实现的接口并设置。

setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));

public static Class<?>[] getAllInterfacesForClass(Class<?> clazz, @Nullable ClassLoader classLoader) {
   return toClassArray(getAllInterfacesForClassAsSet(clazz, classLoader));
}

// 此方法会查找clazz实现的所有接口及其父接口
public static Set<Class<?>> getAllInterfacesForClassAsSet(Class<?> clazz, @Nullable ClassLoader classLoader) {
   Assert.notNull(clazz, "Class must not be null");
   // 如果clazz本身是一个接口,那么将返回它自己
   if (clazz.isInterface() && isVisible(clazz, classLoader)) {
      return Collections.singleton(clazz);
   }
   Set<Class<?>> interfaces = new LinkedHashSet<>();
   Class<?> current = clazz;
   while (current != null) {
      Class<?>[] ifcs = current.getInterfaces();
      for (Class<?> ifc : ifcs) {
         if (isVisible(ifc, classLoader)) {
            interfaces.add(ifc);
         }
      }
      current = current.getSuperclass();
   }
   return interfaces;
}


public void setInterfaces(Class<?>... interfaces) {
   Assert.notNull(interfaces, "Interfaces must not be null");
   this.interfaces.clear();
   for (Class<?> ifc : interfaces) {
      addInterface(ifc);
   }
}

/**
 * Add a new proxied interface.
 * @param intf the additional interface to proxy
 */
public void addInterface(Class<?> intf) {
   Assert.notNull(intf, "Interface must not be null");
   if (!intf.isInterface()) {
      throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
   }
   if (!this.interfaces.contains(intf)) {
      this.interfaces.add(intf);
      adviceChanged();
   }
}

接下来,便是之前说过的根据情况使用jdk或者cglib创建代理对象。

原型

原型对象创建的过程与单例类似,不过多执行了一步拷贝操作。对于一个新的原型对象,需要拷贝一份配置信息,一份拦截器链以及一个TargetSource。当你使用原型模式时,你需要提供一个原型TargetSource以及原型Advisor,此时你的每一个代理对象都将是完全独立的。当然,如果你的这些对象是无状态的,那么效果也类似,唯一可能的问题便是并发争用。

private synchronized Object newPrototypeInstance() {
   // In the case of a prototype, we need to give the proxy
   // an independent instance of the configuration.
   // In this case, no proxy will have an instance of this object's configuration,
   // but will have an independent copy.
   if (logger.isTraceEnabled()) {
      logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);
   }

   ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());
   // The copy needs a fresh advisor chain, and a fresh TargetSource.
   TargetSource targetSource = freshTargetSource();
   copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
   if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
      // Rely on AOP infrastructure to tell us what interfaces to proxy.
      Class<?> targetClass = targetSource.getTargetClass();
      if (targetClass != null) {
         copy.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
      }
   }
   copy.setFrozen(this.freezeProxy);

   if (logger.isTraceEnabled()) {
      logger.trace("Using ProxyCreatorSupport copy: " + copy);
   }
   return getProxy(copy.createAopProxy());
}

private List<Advisor> freshAdvisorChain() {
   Advisor[] advisors = getAdvisors();
   List<Advisor> freshAdvisors = new ArrayList<>(advisors.length);
   for (Advisor advisor : advisors) {
      // 如果是占位Advisor,此时真正获取其bean实例
      if (advisor instanceof PrototypePlaceholderAdvisor) {
         PrototypePlaceholderAdvisor pa = (PrototypePlaceholderAdvisor) advisor;
         if (logger.isDebugEnabled()) {
            logger.debug("Refreshing bean named '" + pa.getBeanName() + "'");
         }
         // Replace the placeholder with a fresh prototype instance resulting
         // from a getBean() lookup
         if (this.beanFactory == null) {
            throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                  "- cannot resolve prototype advisor '" + pa.getBeanName() + "'");
         }
         Object bean = this.beanFactory.getBean(pa.getBeanName());
         Advisor refreshedAdvisor = namedBeanToAdvisor(bean);
         freshAdvisors.add(refreshedAdvisor);
      }
      else {
         // Add the shared instance.
         freshAdvisors.add(advisor);
      }
   }
   return freshAdvisors;
}

其他

当创建完代理对象后,如果通过jdk代理创建,那么你可以将它转变为Advised对象,并且对拦截器链进行增删操作;或者你可以直接获取ProxyFactoryBean对象,并调用其方法增加接口或者修改拦截器链。此时,如果是singleton模式,那么之前缓存的代理对象将会被清除,下一次调用getObject()方法时将会获取一个新的代理对象,但是它们将会共享相同的拦截器链。如果修改的拦截器链,那么新旧两个代理对象还是会享有相同的配置;如果修改的是接口,那么新旧两个代理对象只有接口不同。如果是prototype模式,那么将对之前获取的代理对象毫无影响,只会在下一个调用getObject()方法时将会获取新代理对象。

关于ProxyFactoryBean的更多信息,请查看6.4. Using the ProxyFactoryBean to Create AOP Proxies

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容