Package org.springframework.beans.factory.annotation

Source Code of org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement

/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.beans.factory.annotation;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.LookupOverride;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
* that autowires annotated fields, setter methods and arbitrary config methods.
* Such members to be injected are detected through a Java 5 annotation: by default,
* Spring's {@link Autowired @Autowired} and {@link Value @Value} annotations.
*
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available, as a direct alternative to Spring's own {@code @Autowired}.
*
* <p>Only one constructor (at max) of any given bean class may carry this
* annotation with the 'required' parameter set to {@code true},
* indicating <i>the</i> constructor to autowire when used as a Spring bean.
* If multiple <i>non-required</i> constructors carry the annotation, they
* will be considered as candidates for autowiring. The constructor with
* the greatest number of dependencies that can be satisfied by matching
* beans in the Spring container will be chosen. If none of the candidates
* can be satisfied, then a default constructor (if present) will be used.
* An annotated constructor does not have to be public.
*
* <p>Fields are injected right after construction of a bean, before any
* config methods are invoked. Such a config field does not have to be public.
*
* <p>Config methods may have an arbitrary name and any number of arguments; each of
* those arguments will be autowired with a matching bean in the Spring container.
* Bean property setter methods are effectively just a special case of such a
* general config method. Config methods do not have to be public.
*
* <p>Note: A default AutowiredAnnotationBeanPostProcessor will be registered
* by the "context:annotation-config" and "context:component-scan" XML tags.
* Remove or turn off the default annotation configuration there if you intend
* to specify a custom AutowiredAnnotationBeanPostProcessor bean definition.
* <p><b>NOTE:</b> Annotation injection will be performed <i>before</i> XML injection;
* thus the latter configuration will override the former for properties wired through
* both approaches.
*
* <p>In addition to regular injection points as discussed above, this post-processor
* also handles Spring's {@link Lookup @Lookup} annotation which identifies lookup
* methods to be replaced by the container at runtime. This is essentially a type-safe
* version of {@code getBean(Class, args)} and {@code getBean(String, args)},
* See {@link Lookup @Lookup's javadoc} for details.
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 2.5
* @see #setAutowiredAnnotationType
* @see Autowired
* @see Value
*/
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
    implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {

  protected final Log logger = LogFactory.getLog(getClass());

  private final Set<Class<? extends Annotation>> autowiredAnnotationTypes =
      new LinkedHashSet<Class<? extends Annotation>>();

  private String requiredParameterName = "required";

  private boolean requiredParameterValue = true;

  private int order = Ordered.LOWEST_PRECEDENCE - 2;

  private ConfigurableListableBeanFactory beanFactory;

  private final Set<String> lookupMethodsChecked =
      Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(64));

  private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache =
      new ConcurrentHashMap<Class<?>, Constructor<?>[]>(64);

  private final Map<String, InjectionMetadata> injectionMetadataCache =
      new ConcurrentHashMap<String, InjectionMetadata>(64);


  /**
   * Create a new AutowiredAnnotationBeanPostProcessor
   * for Spring's standard {@link Autowired} annotation.
   * <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.
   */
  @SuppressWarnings("unchecked")
  public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    try {
      this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
          ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
      logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
      // JSR-330 API not available - simply skip.
    }
  }


  /**
   * Set the 'autowired' annotation type, to be used on constructors, fields,
   * setter methods and arbitrary config methods.
   * <p>The default autowired annotation type is the Spring-provided
   * {@link Autowired} annotation, as well as {@link Value}.
   * <p>This setter property exists so that developers can provide their own
   * (non-Spring-specific) annotation type to indicate that a member is
   * supposed to be autowired.
   */
  public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
    Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
    this.autowiredAnnotationTypes.clear();
    this.autowiredAnnotationTypes.add(autowiredAnnotationType);
  }

  /**
   * Set the 'autowired' annotation types, to be used on constructors, fields,
   * setter methods and arbitrary config methods.
   * <p>The default autowired annotation type is the Spring-provided
   * {@link Autowired} annotation, as well as {@link Value}.
   * <p>This setter property exists so that developers can provide their own
   * (non-Spring-specific) annotation types to indicate that a member is
   * supposed to be autowired.
   */
  public void setAutowiredAnnotationTypes(Set<Class<? extends Annotation>> autowiredAnnotationTypes) {
    Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
    this.autowiredAnnotationTypes.clear();
    this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
  }

  /**
   * Set the name of a parameter of the annotation that specifies
   * whether it is required.
   * @see #setRequiredParameterValue(boolean)
   */
  public void setRequiredParameterName(String requiredParameterName) {
    this.requiredParameterName = requiredParameterName;
  }

  /**
   * Set the boolean value that marks a dependency as required
   * <p>For example if using 'required=true' (the default),
   * this value should be {@code true}; but if using
   * 'optional=false', this value should be {@code false}.
   * @see #setRequiredParameterName(String)
   */
  public void setRequiredParameterValue(boolean requiredParameterValue) {
    this.requiredParameterValue = requiredParameterValue;
  }

  public void setOrder(int order) {
    this.order = order;
  }

  @Override
  public int getOrder() {
    return this.order;
  }

  @Override
  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
      throw new IllegalArgumentException(
          "AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
    }
    this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
  }


  @Override
  public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    if (beanType != null) {
      InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType);
      metadata.checkConfigMembers(beanDefinition);
    }
  }

  @Override
  public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeansException {
    if (!this.lookupMethodsChecked.contains(beanName)) {
      ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
        @Override
        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
          Lookup lookup = method.getAnnotation(Lookup.class);
          if (lookup != null) {
            LookupOverride override = new LookupOverride(method, lookup.value());
            try {
              RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
              mbd.getMethodOverrides().addOverride(override);
            }
            catch (NoSuchBeanDefinitionException ex) {
              throw new BeanCreationException(beanName,
                  "Cannot apply @Lookup to beans without corresponding bean definition");
            }
          }
        }
      });
      this.lookupMethodsChecked.add(beanName);
    }

    // Quick check on the concurrent map first, with minimal locking.
    Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    if (candidateConstructors == null) {
      synchronized (this.candidateConstructorsCache) {
        candidateConstructors = this.candidateConstructorsCache.get(beanClass);
        if (candidateConstructors == null) {
          Constructor<?>[] rawCandidates = beanClass.getDeclaredConstructors();
          List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
          Constructor<?> requiredConstructor = null;
          Constructor<?> defaultConstructor = null;
          for (Constructor<?> candidate : rawCandidates) {
            AnnotationAttributes annotation = findAutowiredAnnotation(candidate);
            if (annotation != null) {
              if (requiredConstructor != null) {
                throw new BeanCreationException(beanName,
                    "Invalid autowire-marked constructor: " + candidate +
                    ". Found constructor with 'required' Autowired annotation already: " +
                    requiredConstructor);
              }
              if (candidate.getParameterTypes().length == 0) {
                throw new IllegalStateException(
                    "Autowired annotation requires at least one argument: " + candidate);
              }
              boolean required = determineRequiredStatus(annotation);
              if (required) {
                if (!candidates.isEmpty()) {
                  throw new BeanCreationException(beanName,
                      "Invalid autowire-marked constructors: " + candidates +
                      ". Found constructor with 'required' Autowired annotation: " +
                      candidate);
                }
                requiredConstructor = candidate;
              }
              candidates.add(candidate);
            }
            else if (candidate.getParameterTypes().length == 0) {
              defaultConstructor = candidate;
            }
          }
          if (!candidates.isEmpty()) {
            // Add default constructor to list of optional constructors, as fallback.
            if (requiredConstructor == null) {
              if (defaultConstructor != null) {
                candidates.add(defaultConstructor);
              }
              else if (candidates.size() == 1 && logger.isWarnEnabled()) {
                logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
                    "': single autowire-marked constructor flagged as optional - this constructor " +
                    "is effectively required since there is no default constructor to fall back to: " +
                    candidates.get(0));
              }
            }
            candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
          }
          else {
            candidateConstructors = new Constructor<?>[0];
          }
          this.candidateConstructorsCache.put(beanClass, candidateConstructors);
        }
      }
    }
    return (candidateConstructors.length > 0 ? candidateConstructors : null);
  }

  @Override
  public PropertyValues postProcessPropertyValues(
      PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass());
    try {
      metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
  }

  /**
   * 'Native' processing method for direct calls with an arbitrary target instance,
   * resolving all of its fields and methods which are annotated with {@code @Autowired}.
   * @param bean the target instance to process
   * @throws BeansException if autowiring failed
   */
  public void processInjection(Object bean) throws BeansException {
    Class<?> clazz = bean.getClass();
    InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz);
    try {
      metadata.inject(bean, null, null);
    }
    catch (Throwable ex) {
      throw new BeanCreationException("Injection of autowired dependencies failed for class [" + clazz + "]", ex);
    }
  }


  private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz) {
    // Quick check on the concurrent map first, with minimal locking.
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
      synchronized (this.injectionMetadataCache) {
        metadata = this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
          metadata = buildAutowiringMetadata(clazz);
          this.injectionMetadataCache.put(cacheKey, metadata);
        }
      }
    }
    return metadata;
  }

  private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
    Class<?> targetClass = clazz;

    do {
      LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
      for (Field field : targetClass.getDeclaredFields()) {
        AnnotationAttributes annotation = findAutowiredAnnotation(field);
        if (annotation != null) {
          if (Modifier.isStatic(field.getModifiers())) {
            if (logger.isWarnEnabled()) {
              logger.warn("Autowired annotation is not supported on static fields: " + field);
            }
            continue;
          }
          boolean required = determineRequiredStatus(annotation);
          currElements.add(new AutowiredFieldElement(field, required));
        }
      }
      for (Method method : targetClass.getDeclaredMethods()) {
        AnnotationAttributes ann = null;
        Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
        if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
          ann = findAutowiredAnnotation(bridgedMethod);
        }
        else if (!method.isBridge()) {
          ann = findAutowiredAnnotation(method);
        }
        if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
          if (Modifier.isStatic(method.getModifiers())) {
            if (logger.isWarnEnabled()) {
              logger.warn("Autowired annotation is not supported on static methods: " + method);
            }
            continue;
          }
          if (method.getParameterTypes().length == 0) {
            if (logger.isWarnEnabled()) {
              logger.warn("Autowired annotation should be used on methods with actual parameters: " + method);
            }
          }
          boolean required = determineRequiredStatus(ann);
          PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
          currElements.add(new AutowiredMethodElement(method, required, pd));
        }
      }
      elements.addAll(0, currElements);
      targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new InjectionMetadata(clazz, elements);
  }

  private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
    for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
      AnnotationAttributes annotation = AnnotatedElementUtils.getAnnotationAttributes(ao, type.getName());
      if (annotation != null) {
        return annotation;
      }
    }
    return null;
  }

  /**
   * Determine if the annotated field or method requires its dependency.
   * <p>A 'required' dependency means that autowiring should fail when no beans
   * are found. Otherwise, the autowiring process will simply bypass the field
   * or method when no beans are found.
   * @param annotation the Autowired annotation
   * @return whether the annotation indicates that a dependency is required
   */
  protected boolean determineRequiredStatus(AnnotationAttributes annotation) {
    return (!annotation.containsKey(this.requiredParameterName) ||
        this.requiredParameterValue == annotation.getBoolean(this.requiredParameterName));
  }

  /**
   * Obtain all beans of the given type as autowire candidates.
   * @param type the type of the bean
   * @return the target beans, or an empty Collection if no bean of this type is found
   * @throws BeansException if bean retrieval failed
   */
  protected <T> Map<String, T> findAutowireCandidates(Class<T> type) throws BeansException {
    if (this.beanFactory == null) {
      throw new IllegalStateException("No BeanFactory configured - " +
          "override the getBeanOfType method or specify the 'beanFactory' property");
    }
    return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type);
  }

  /**
   * Register the specified bean as dependent on the autowired beans.
   */
  private void registerDependentBeans(String beanName, Set<String> autowiredBeanNames) {
    if (beanName != null) {
      for (String autowiredBeanName : autowiredBeanNames) {
        if (this.beanFactory.containsBean(autowiredBeanName)) {
          this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
        }
        if (logger.isDebugEnabled()) {
          logger.debug("Autowiring by type from bean name '" + beanName +
              "' to bean named '" + autowiredBeanName + "'");
        }
      }
    }
  }

  /**
   * Resolve the specified cached method argument or field value.
   */
  private Object resolvedCachedArgument(String beanName, Object cachedArgument) {
    if (cachedArgument instanceof DependencyDescriptor) {
      DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
      return this.beanFactory.resolveDependency(descriptor, beanName, null, null);
    }
    else if (cachedArgument instanceof RuntimeBeanReference) {
      return this.beanFactory.getBean(((RuntimeBeanReference) cachedArgument).getBeanName());
    }
    else {
      return cachedArgument;
    }
  }


  /**
   * Class representing injection information about an annotated field.
   */
  private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

    private final boolean required;

    private volatile boolean cached = false;

    private volatile Object cachedFieldValue;

    public AutowiredFieldElement(Field field, boolean required) {
      super(field, null);
      this.required = required;
    }

    @Override
    protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
      Field field = (Field) this.member;
      try {
        Object value;
        if (this.cached) {
          value = resolvedCachedArgument(beanName, this.cachedFieldValue);
        }
        else {
          DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
          desc.setContainingClass(bean.getClass());
          Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
          TypeConverter typeConverter = beanFactory.getTypeConverter();
          value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
          synchronized (this) {
            if (!this.cached) {
              if (value != null || this.required) {
                this.cachedFieldValue = desc;
                registerDependentBeans(beanName, autowiredBeanNames);
                if (autowiredBeanNames.size() == 1) {
                  String autowiredBeanName = autowiredBeanNames.iterator().next();
                  if (beanFactory.containsBean(autowiredBeanName)) {
                    if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                      this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
                    }
                  }
                }
              }
              else {
                this.cachedFieldValue = null;
              }
              this.cached = true;
            }
          }
        }
        if (value != null) {
          ReflectionUtils.makeAccessible(field);
          field.set(bean, value);
        }
      }
      catch (Throwable ex) {
        throw new BeanCreationException("Could not autowire field: " + field, ex);
      }
    }
  }


  /**
   * Class representing injection information about an annotated method.
   */
  private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {

    private final boolean required;

    private volatile boolean cached = false;

    private volatile Object[] cachedMethodArguments;

    public AutowiredMethodElement(Method method, boolean required, PropertyDescriptor pd) {
      super(method, pd);
      this.required = required;
    }

    @Override
    protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
      if (checkPropertySkipping(pvs)) {
        return;
      }
      Method method = (Method) this.member;
      try {
        Object[] arguments;
        if (this.cached) {
          // Shortcut for avoiding synchronization...
          arguments = resolveCachedArguments(beanName);
        }
        else {
          Class<?>[] paramTypes = method.getParameterTypes();
          arguments = new Object[paramTypes.length];
          DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
          Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
          TypeConverter typeConverter = beanFactory.getTypeConverter();
          for (int i = 0; i < arguments.length; i++) {
            MethodParameter methodParam = new MethodParameter(method, i);
            DependencyDescriptor desc = new DependencyDescriptor(methodParam, this.required);
            desc.setContainingClass(bean.getClass());
            descriptors[i] = desc;
            Object arg = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
            if (arg == null && !this.required) {
              arguments = null;
              break;
            }
            arguments[i] = arg;
          }
          synchronized (this) {
            if (!this.cached) {
              if (arguments != null) {
                this.cachedMethodArguments = new Object[arguments.length];
                for (int i = 0; i < arguments.length; i++) {
                  this.cachedMethodArguments[i] = descriptors[i];
                }
                registerDependentBeans(beanName, autowiredBeanNames);
                if (autowiredBeanNames.size() == paramTypes.length) {
                  Iterator<String> it = autowiredBeanNames.iterator();
                  for (int i = 0; i < paramTypes.length; i++) {
                    String autowiredBeanName = it.next();
                    if (beanFactory.containsBean(autowiredBeanName)) {
                      if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
                        this.cachedMethodArguments[i] = new RuntimeBeanReference(autowiredBeanName);
                      }
                    }
                  }
                }
              }
              else {
                this.cachedMethodArguments = null;
              }
              this.cached = true;
            }
          }
        }
        if (arguments != null) {
          ReflectionUtils.makeAccessible(method);
          method.invoke(bean, arguments);
        }
      }
      catch (InvocationTargetException ex) {
        throw ex.getTargetException();
      }
      catch (Throwable ex) {
        throw new BeanCreationException("Could not autowire method: " + method, ex);
      }
    }

    private Object[] resolveCachedArguments(String beanName) {
      if (this.cachedMethodArguments == null) {
        return null;
      }
      Object[] arguments = new Object[this.cachedMethodArguments.length];
      for (int i = 0; i < arguments.length; i++) {
        arguments[i] = resolvedCachedArgument(beanName, this.cachedMethodArguments[i]);
      }
      return arguments;
    }
  }

}
TOP

Related Classes of org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.