首页

关于spring-beans包中InjectionPoint注入切面点的源代码实现分析说明

标签:spring-beans,InjectionPoint,面向切面源码,AOP,springframework     发布时间:2018-09-05   

一、前言

关于spring-beans包中org.springframework.beans.factory.InjectionPoint注入点类,涉及方法参数org.springframework.beans.factory.MethodParameter(详情参见spring-core)、属性java.lang.reflect.Field、java.lang.annotation.Annotation[]数组成员变量,详情参见源码说明。

二、源码说明

1. InjectionPoint类

package org.springframework.beans.factory;@b@@b@import java.lang.annotation.Annotation;@b@import java.lang.reflect.AnnotatedElement;@b@import java.lang.reflect.Field;@b@import java.lang.reflect.Member;@b@import org.springframework.core.MethodParameter;@b@import org.springframework.util.Assert;@b@@b@public class InjectionPoint@b@{@b@  protected MethodParameter methodParameter;@b@  protected Field field;@b@  private volatile Annotation[] fieldAnnotations;@b@@b@  public InjectionPoint(MethodParameter methodParameter)@b@  {@b@    Assert.notNull(methodParameter, "MethodParameter must not be null");@b@    this.methodParameter = methodParameter;@b@  }@b@@b@  public InjectionPoint(Field field)@b@  {@b@    Assert.notNull(field, "Field must not be null");@b@    this.field = field;@b@  }@b@@b@  protected InjectionPoint(InjectionPoint original)@b@  {@b@    this.methodParameter = ((original.methodParameter != null) ? new MethodParameter(original.methodParameter) : null);@b@@b@    this.field = original.field;@b@    this.fieldAnnotations = original.fieldAnnotations;@b@  }@b@@b@  protected InjectionPoint()@b@  {@b@  }@b@@b@  public MethodParameter getMethodParameter()@b@  {@b@    return this.methodParameter;@b@  }@b@@b@  public Field getField()@b@  {@b@    return this.field;@b@  }@b@@b@  public Annotation[] getAnnotations()@b@  {@b@    if (this.field != null) {@b@      if (this.fieldAnnotations == null)@b@        this.fieldAnnotations = this.field.getAnnotations();@b@@b@      return this.fieldAnnotations;@b@    }@b@@b@    return this.methodParameter.getParameterAnnotations();@b@  }@b@@b@  public <A extends Annotation> A getAnnotation(Class<A> annotationType)@b@  {@b@    return ((this.field != null) ? this.field.getAnnotation(annotationType) : this.methodParameter@b@      .getParameterAnnotation(annotationType));@b@  }@b@@b@  public Class<?> getDeclaredType()@b@  {@b@    return ((this.field != null) ? this.field.getType() : this.methodParameter.getParameterType());@b@  }@b@@b@  public Member getMember()@b@  {@b@    return ((this.field != null) ? this.field : this.methodParameter.getMember());@b@  }@b@@b@  public AnnotatedElement getAnnotatedElement()@b@  {@b@    return ((this.field != null) ? this.field : this.methodParameter.getAnnotatedElement());@b@  }@b@@b@  public boolean equals(Object other)@b@  {@b@    if (this == other)@b@      return true;@b@@b@    if (super.getClass() != other.getClass())@b@      return false;@b@@b@    InjectionPoint otherPoint = (InjectionPoint)other;@b@    return ((this.field != null) ? this.field.equals(otherPoint.field) : this.methodParameter@b@      .equals(otherPoint.methodParameter));@b@  }@b@@b@  public int hashCode()@b@  {@b@    return ((this.field != null) ? this.field.hashCode() : this.methodParameter.hashCode());@b@  }@b@@b@  public String toString()@b@  {@b@    return ((this.field != null) ? "field '" + this.field.getName() + "'" : this.methodParameter.toString());@b@  }@b@}

2. MethodParameter类

package org.springframework.core;@b@@b@import java.lang.annotation.Annotation;@b@import java.lang.reflect.AnnotatedElement;@b@import java.lang.reflect.Constructor;@b@import java.lang.reflect.Member;@b@import java.lang.reflect.Method;@b@import java.lang.reflect.ParameterizedType;@b@import java.lang.reflect.Type;@b@import java.util.HashMap;@b@import java.util.Map;@b@import org.springframework.util.Assert;@b@import org.springframework.util.ClassUtils;@b@@b@public class MethodParameter@b@{@b@  private static final Class<?> javaUtilOptionalClass;@b@  private final Method method;@b@  private final Constructor<?> constructor;@b@  private final int parameterIndex;@b@  private int nestingLevel;@b@  Map<Integer, Integer> typeIndexesPerLevel;@b@  private volatile Class<?> containingClass;@b@  private volatile Class<?> parameterType;@b@  private volatile Type genericParameterType;@b@  private volatile Annotation[] parameterAnnotations;@b@  private volatile ParameterNameDiscoverer parameterNameDiscoverer;@b@  private volatile String parameterName;@b@  private volatile MethodParameter nestedMethodParameter;@b@@b@  public MethodParameter(Method method, int parameterIndex)@b@  {@b@    this(method, parameterIndex, 1);@b@  }@b@@b@  public MethodParameter(Method method, int parameterIndex, int nestingLevel)@b@  {@b@    this.nestingLevel = 1;@b@@b@    Assert.notNull(method, "Method must not be null");@b@    this.method = method;@b@    this.parameterIndex = parameterIndex;@b@    this.nestingLevel = nestingLevel;@b@    this.constructor = null;@b@  }@b@@b@  public MethodParameter(Constructor<?> constructor, int parameterIndex)@b@  {@b@    this(constructor, parameterIndex, 1);@b@  }@b@@b@  public MethodParameter(Constructor<?> constructor, int parameterIndex, int nestingLevel)@b@  {@b@    this.nestingLevel = 1;@b@@b@    Assert.notNull(constructor, "Constructor must not be null");@b@    this.constructor = constructor;@b@    this.parameterIndex = parameterIndex;@b@    this.nestingLevel = nestingLevel;@b@    this.method = null;@b@  }@b@@b@  public MethodParameter(MethodParameter original)@b@  {@b@    this.nestingLevel = 1;@b@@b@    Assert.notNull(original, "Original must not be null");@b@    this.method = original.method;@b@    this.constructor = original.constructor;@b@    this.parameterIndex = original.parameterIndex;@b@    this.nestingLevel = original.nestingLevel;@b@    this.typeIndexesPerLevel = original.typeIndexesPerLevel;@b@    this.containingClass = original.containingClass;@b@    this.parameterType = original.parameterType;@b@    this.genericParameterType = original.genericParameterType;@b@    this.parameterAnnotations = original.parameterAnnotations;@b@    this.parameterNameDiscoverer = original.parameterNameDiscoverer;@b@    this.parameterName = original.parameterName;@b@  }@b@@b@  public Method getMethod()@b@  {@b@    return this.method;@b@  }@b@@b@  public Constructor<?> getConstructor()@b@  {@b@    return this.constructor;@b@  }@b@@b@  public Class<?> getDeclaringClass()@b@  {@b@    return getMember().getDeclaringClass();@b@  }@b@@b@  public Member getMember()@b@  {@b@    if (this.method != null) {@b@      return this.method;@b@    }@b@@b@    return this.constructor;@b@  }@b@@b@  public AnnotatedElement getAnnotatedElement()@b@  {@b@    if (this.method != null) {@b@      return this.method;@b@    }@b@@b@    return this.constructor;@b@  }@b@@b@  public int getParameterIndex()@b@  {@b@    return this.parameterIndex;@b@  }@b@@b@  public void increaseNestingLevel()@b@  {@b@    this.nestingLevel += 1;@b@  }@b@@b@  public void decreaseNestingLevel()@b@  {@b@    getTypeIndexesPerLevel().remove(Integer.valueOf(this.nestingLevel));@b@    this.nestingLevel -= 1;@b@  }@b@@b@  public int getNestingLevel()@b@  {@b@    return this.nestingLevel;@b@  }@b@@b@  public void setTypeIndexForCurrentLevel(int typeIndex)@b@  {@b@    getTypeIndexesPerLevel().put(Integer.valueOf(this.nestingLevel), Integer.valueOf(typeIndex));@b@  }@b@@b@  public Integer getTypeIndexForCurrentLevel()@b@  {@b@    return getTypeIndexForLevel(this.nestingLevel);@b@  }@b@@b@  public Integer getTypeIndexForLevel(int nestingLevel)@b@  {@b@    return ((Integer)getTypeIndexesPerLevel().get(Integer.valueOf(nestingLevel)));@b@  }@b@@b@  private Map<Integer, Integer> getTypeIndexesPerLevel()@b@  {@b@    if (this.typeIndexesPerLevel == null)@b@      this.typeIndexesPerLevel = new HashMap(4);@b@@b@    return this.typeIndexesPerLevel;@b@  }@b@@b@  public MethodParameter nested()@b@  {@b@    if (this.nestedMethodParameter != null)@b@      return this.nestedMethodParameter;@b@@b@    MethodParameter nestedParam = clone();@b@    nestedParam.nestingLevel = (this.nestingLevel + 1);@b@    this.nestedMethodParameter = nestedParam;@b@    return nestedParam;@b@  }@b@@b@  public boolean isOptional()@b@  {@b@    return (getParameterType() == javaUtilOptionalClass);@b@  }@b@@b@  public MethodParameter nestedIfOptional()@b@  {@b@    return ((isOptional()) ? nested() : this);@b@  }@b@@b@  void setContainingClass(Class<?> containingClass)@b@  {@b@    this.containingClass = containingClass;@b@  }@b@@b@  public Class<?> getContainingClass() {@b@    return ((this.containingClass != null) ? this.containingClass : getDeclaringClass());@b@  }@b@@b@  void setParameterType(Class<?> parameterType)@b@  {@b@    this.parameterType = parameterType;@b@  }@b@@b@  public Class<?> getParameterType()@b@  {@b@    Class paramType = this.parameterType;@b@    if (paramType == null) {@b@      if (this.parameterIndex < 0) {@b@        Method method = getMethod();@b@        paramType = (method != null) ? method.getReturnType() : Void.TYPE;@b@      }@b@      else@b@      {@b@        paramType = (this.method != null) ? this.method@b@          .getParameterTypes()[this.parameterIndex] : this.constructor@b@          .getParameterTypes()[this.parameterIndex];@b@      }@b@      this.parameterType = paramType;@b@    }@b@    return paramType;@b@  }@b@@b@  public Type getGenericParameterType()@b@  {@b@    Type paramType = this.genericParameterType;@b@    if (paramType == null) {@b@      if (this.parameterIndex < 0) {@b@        Method method = getMethod();@b@        paramType = (method != null) ? method.getGenericReturnType() : Void.TYPE;@b@      }@b@      else@b@      {@b@        paramType = (this.method != null) ? this.method@b@          .getGenericParameterTypes()[this.parameterIndex] : this.constructor@b@          .getGenericParameterTypes()[this.parameterIndex];@b@      }@b@      this.genericParameterType = paramType;@b@    }@b@    return paramType;@b@  }@b@@b@  public Class<?> getNestedParameterType()@b@  {@b@    if (this.nestingLevel > 1) {@b@      Type type = getGenericParameterType();@b@      for (int i = 2; i <= this.nestingLevel; ++i)@b@        if (type instanceof ParameterizedType) {@b@          Type[] args = ((ParameterizedType)type).getActualTypeArguments();@b@          Integer index = getTypeIndexForLevel(i);@b@          type = args[(args.length - 1)];@b@        }@b@@b@@b@      if (type instanceof Class)@b@        return ((Class)type);@b@@b@      if (type instanceof ParameterizedType) {@b@        Type arg = ((ParameterizedType)type).getRawType();@b@        if (arg instanceof Class)@b@          return ((Class)arg);@b@      }@b@@b@      return Object.class;@b@    }@b@@b@    return getParameterType();@b@  }@b@@b@  public Type getNestedGenericParameterType()@b@  {@b@    if (this.nestingLevel > 1) {@b@      Type type = getGenericParameterType();@b@      for (int i = 2; i <= this.nestingLevel; ++i)@b@        if (type instanceof ParameterizedType) {@b@          Type[] args = ((ParameterizedType)type).getActualTypeArguments();@b@          Integer index = getTypeIndexForLevel(i);@b@          type = args[(args.length - 1)];@b@        }@b@@b@      return type;@b@    }@b@@b@    return getGenericParameterType();@b@  }@b@@b@  public Annotation[] getMethodAnnotations()@b@  {@b@    return adaptAnnotationArray(getAnnotatedElement().getAnnotations());@b@  }@b@@b@  public <A extends Annotation> A getMethodAnnotation(Class<A> annotationType)@b@  {@b@    return adaptAnnotation(getAnnotatedElement().getAnnotation(annotationType));@b@  }@b@@b@  public <A extends Annotation> boolean hasMethodAnnotation(Class<A> annotationType)@b@  {@b@    return getAnnotatedElement().isAnnotationPresent(annotationType);@b@  }@b@@b@  public Annotation[] getParameterAnnotations()@b@  {@b@    if (this.parameterAnnotations == null)@b@    {@b@      Annotation[][] annotationArray = (this.method != null) ? this.method@b@        .getParameterAnnotations() : this.constructor.getParameterAnnotations();@b@      if ((this.parameterIndex >= 0) && (this.parameterIndex < annotationArray.length)) {@b@        this.parameterAnnotations = adaptAnnotationArray(annotationArray[this.parameterIndex]);@b@      }@b@      else@b@        this.parameterAnnotations = new Annotation[0];@b@    }@b@@b@    return this.parameterAnnotations;@b@  }@b@@b@  public boolean hasParameterAnnotations()@b@  {@b@    return (getParameterAnnotations().length != 0);@b@  }@b@@b@  public <A extends Annotation> A getParameterAnnotation(Class<A> annotationType)@b@  {@b@    Annotation[] anns = getParameterAnnotations();@b@    Annotation[] arrayOfAnnotation1 = anns; int i = arrayOfAnnotation1.length; for (int j = 0; j < i; ++j) { Annotation ann = arrayOfAnnotation1[j];@b@      if (annotationType.isInstance(ann))@b@        return ann;@b@    }@b@@b@    return null;@b@  }@b@@b@  public <A extends Annotation> boolean hasParameterAnnotation(Class<A> annotationType)@b@  {@b@    return (getParameterAnnotation(annotationType) != null);@b@  }@b@@b@  public void initParameterNameDiscovery(ParameterNameDiscoverer parameterNameDiscoverer)@b@  {@b@    this.parameterNameDiscoverer = parameterNameDiscoverer;@b@  }@b@@b@  public String getParameterName()@b@  {@b@    ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;@b@    if (discoverer != null)@b@    {@b@      String[] parameterNames = (this.method != null) ? discoverer@b@        .getParameterNames(this.method)@b@         : discoverer.getParameterNames(this.constructor);@b@      if (parameterNames != null)@b@        this.parameterName = parameterNames[this.parameterIndex];@b@@b@      this.parameterNameDiscoverer = null;@b@    }@b@    return this.parameterName;@b@  }@b@@b@  protected <A extends Annotation> A adaptAnnotation(A annotation)@b@  {@b@    return annotation;@b@  }@b@@b@  protected Annotation[] adaptAnnotationArray(Annotation[] annotations)@b@  {@b@    return annotations;@b@  }@b@@b@  public boolean equals(Object other)@b@  {@b@    if (this == other)@b@      return true;@b@@b@    if (!(other instanceof MethodParameter))@b@      return false;@b@@b@    MethodParameter otherParam = (MethodParameter)other;@b@    return ((this.parameterIndex == otherParam.parameterIndex) && (getMember().equals(otherParam.getMember())));@b@  }@b@@b@  public int hashCode()@b@  {@b@    return (getMember().hashCode() * 31 + this.parameterIndex);@b@  }@b@@b@  public String toString()@b@  {@b@    return new StringBuilder().append((this.method != null) ? new StringBuilder().append("method '").append(this.method.getName()).append("'").toString() : "constructor").append(" parameter ").append(this.parameterIndex).toString();@b@  }@b@@b@  public MethodParameter clone()@b@  {@b@    return new MethodParameter(this);@b@  }@b@@b@  public static MethodParameter forMethodOrConstructor(Object methodOrConstructor, int parameterIndex)@b@  {@b@    if (methodOrConstructor instanceof Method)@b@      return new MethodParameter((Method)methodOrConstructor, parameterIndex);@b@@b@    if (methodOrConstructor instanceof Constructor) {@b@      return new MethodParameter((Constructor)methodOrConstructor, parameterIndex);@b@    }@b@@b@    throw new IllegalArgumentException(new StringBuilder().append("Given object [").append(methodOrConstructor).append("] is neither a Method nor a Constructor").toString());@b@  }@b@@b@  static@b@  {@b@    Class clazz;@b@    try@b@    {@b@      clazz = ClassUtils.forName("java.util.Optional", MethodParameter.class.getClassLoader());@b@    }@b@    catch (ClassNotFoundException ex)@b@    {@b@      clazz = null;@b@    }@b@    javaUtilOptionalClass = clazz;@b@  }@b@}

3. DependencyDescriptor继承InjectionPoint用法

package org.springframework.beans.factory.config;@b@@b@import java.io.IOException;@b@import java.io.ObjectInputStream;@b@import java.io.Serializable;@b@import java.lang.reflect.Constructor;@b@import java.lang.reflect.Field;@b@import java.lang.reflect.Method;@b@import java.lang.reflect.ParameterizedType;@b@import java.lang.reflect.Type;@b@import java.util.Map;@b@import org.springframework.beans.BeansException;@b@import org.springframework.beans.factory.BeanFactory;@b@import org.springframework.beans.factory.InjectionPoint;@b@import org.springframework.beans.factory.NoUniqueBeanDefinitionException;@b@import org.springframework.core.GenericCollectionTypeResolver;@b@import org.springframework.core.GenericTypeResolver;@b@import org.springframework.core.MethodParameter;@b@import org.springframework.core.ParameterNameDiscoverer;@b@import org.springframework.core.ResolvableType;@b@@b@public class DependencyDescriptor extends InjectionPoint@b@  implements Serializable@b@{@b@  private final Class<?> declaringClass;@b@  private String methodName;@b@  private Class<?>[] parameterTypes;@b@  private int parameterIndex;@b@  private String fieldName;@b@  private final boolean required;@b@  private final boolean eager;@b@  private int nestingLevel;@b@  private Class<?> containingClass;@b@  private volatile ResolvableType resolvableType;@b@@b@  public DependencyDescriptor(MethodParameter methodParameter, boolean required)@b@  {@b@    this(methodParameter, required, true);@b@  }@b@@b@  public DependencyDescriptor(MethodParameter methodParameter, boolean required, boolean eager)@b@  {@b@    super(methodParameter);@b@@b@    this.nestingLevel = 1;@b@@b@    this.declaringClass = methodParameter.getDeclaringClass();@b@    if (this.methodParameter.getMethod() != null) {@b@      this.methodName = methodParameter.getMethod().getName();@b@      this.parameterTypes = methodParameter.getMethod().getParameterTypes();@b@    }@b@    else {@b@      this.parameterTypes = methodParameter.getConstructor().getParameterTypes();@b@    }@b@    this.parameterIndex = methodParameter.getParameterIndex();@b@    this.containingClass = methodParameter.getContainingClass();@b@    this.required = required;@b@    this.eager = eager;@b@  }@b@@b@  public DependencyDescriptor(Field field, boolean required)@b@  {@b@    this(field, required, true);@b@  }@b@@b@  public DependencyDescriptor(Field field, boolean required, boolean eager)@b@  {@b@    super(field);@b@@b@    this.nestingLevel = 1;@b@@b@    this.declaringClass = field.getDeclaringClass();@b@    this.fieldName = field.getName();@b@    this.required = required;@b@    this.eager = eager;@b@  }@b@@b@  public DependencyDescriptor(DependencyDescriptor original)@b@  {@b@    super(original);@b@@b@    this.nestingLevel = 1;@b@@b@    this.declaringClass = original.declaringClass;@b@    this.methodName = original.methodName;@b@    this.parameterTypes = original.parameterTypes;@b@    this.parameterIndex = original.parameterIndex;@b@    this.fieldName = original.fieldName;@b@    this.containingClass = original.containingClass;@b@    this.required = original.required;@b@    this.eager = original.eager;@b@    this.nestingLevel = original.nestingLevel;@b@  }@b@@b@  public boolean isRequired()@b@  {@b@    return this.required;@b@  }@b@@b@  public boolean isEager()@b@  {@b@    return this.eager;@b@  }@b@@b@  public Object resolveNotUnique(Class<?> type, Map<String, Object> matchingBeans)@b@    throws BeansException@b@  {@b@    throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());@b@  }@b@@b@  public Object resolveShortcut(BeanFactory beanFactory)@b@    throws BeansException@b@  {@b@    return null;@b@  }@b@@b@  public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)@b@    throws BeansException@b@  {@b@    return beanFactory.getBean(beanName, requiredType);@b@  }@b@@b@  public void increaseNestingLevel()@b@  {@b@    this.nestingLevel += 1;@b@    this.resolvableType = null;@b@    if (this.methodParameter != null)@b@      this.methodParameter.increaseNestingLevel();@b@  }@b@@b@  public void setContainingClass(Class<?> containingClass)@b@  {@b@    this.containingClass = containingClass;@b@    this.resolvableType = null;@b@    if (this.methodParameter != null)@b@      GenericTypeResolver.resolveParameterType(this.methodParameter, containingClass);@b@  }@b@@b@  public ResolvableType getResolvableType()@b@  {@b@    ResolvableType resolvableType = this.resolvableType;@b@    if (resolvableType == null)@b@    {@b@      resolvableType = (this.field != null) ? @b@        ResolvableType.forField(this.field, this.nestingLevel, this.containingClass)@b@         : @b@        ResolvableType.forMethodParameter(this.methodParameter);@b@@b@      this.resolvableType = resolvableType;@b@    }@b@    return resolvableType;@b@  }@b@@b@  public boolean fallbackMatchAllowed()@b@  {@b@    return false;@b@  }@b@@b@  public DependencyDescriptor forFallbackMatch()@b@  {@b@    return new DependencyDescriptor(this, this)@b@    {@b@      public boolean fallbackMatchAllowed() {@b@        return true;@b@      }@b@    };@b@  }@b@@b@  public void initParameterNameDiscovery(ParameterNameDiscoverer parameterNameDiscoverer)@b@  {@b@    if (this.methodParameter != null)@b@      this.methodParameter.initParameterNameDiscovery(parameterNameDiscoverer);@b@  }@b@@b@  public String getDependencyName()@b@  {@b@    return ((this.field != null) ? this.field.getName() : this.methodParameter.getParameterName());@b@  }@b@@b@  public Class<?> getDependencyType()@b@  {@b@    if (this.field != null) {@b@      if (this.nestingLevel > 1) {@b@        Type type = this.field.getGenericType();@b@        for (int i = 2; i <= this.nestingLevel; ++i)@b@          if (type instanceof ParameterizedType) {@b@            Type[] args = ((ParameterizedType)type).getActualTypeArguments();@b@            type = args[(args.length - 1)];@b@          }@b@@b@@b@        if (type instanceof Class)@b@          return ((Class)type);@b@@b@        if (type instanceof ParameterizedType) {@b@          Type arg = ((ParameterizedType)type).getRawType();@b@          if (arg instanceof Class)@b@            return ((Class)arg);@b@        }@b@@b@        return Object.class;@b@      }@b@@b@      return this.field.getType();@b@    }@b@@b@    return this.methodParameter.getNestedParameterType();@b@  }@b@@b@  @Deprecated@b@  public Class<?> getCollectionType()@b@  {@b@    return ((this.field != null) ? @b@      GenericCollectionTypeResolver.getCollectionFieldType(this.field, this.nestingLevel)@b@       : @b@      GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter));@b@  }@b@@b@  @Deprecated@b@  public Class<?> getMapKeyType()@b@  {@b@    return ((this.field != null) ? @b@      GenericCollectionTypeResolver.getMapKeyFieldType(this.field, this.nestingLevel)@b@       : @b@      GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter));@b@  }@b@@b@  @Deprecated@b@  public Class<?> getMapValueType()@b@  {@b@    return ((this.field != null) ? @b@      GenericCollectionTypeResolver.getMapValueFieldType(this.field, this.nestingLevel)@b@       : @b@      GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter));@b@  }@b@@b@  public boolean equals(Object other)@b@  {@b@    if (this == other)@b@      return true;@b@@b@    if (!(super.equals(other)))@b@      return false;@b@@b@    DependencyDescriptor otherDesc = (DependencyDescriptor)other;@b@    return ((this.required == otherDesc.required) && (this.eager == otherDesc.eager) && (this.nestingLevel == otherDesc.nestingLevel) && (this.containingClass == otherDesc.containingClass));@b@  }@b@@b@  private void readObject(ObjectInputStream ois)@b@    throws IOException, ClassNotFoundException@b@  {@b@    int i;@b@    ois.defaultReadObject();@b@    try@b@    {@b@      if (this.fieldName != null) {@b@        this.field = this.declaringClass.getDeclaredField(this.fieldName);@b@      }@b@      else {@b@        if (this.methodName != null) {@b@          this.methodParameter = @b@            new MethodParameter(this.declaringClass@b@            .getDeclaredMethod(this.methodName, this.parameterTypes), @b@            this.parameterIndex);@b@        }@b@        else@b@          this.methodParameter = @b@            new MethodParameter(this.declaringClass@b@            .getDeclaredConstructor(this.parameterTypes), @b@            this.parameterIndex);@b@@b@        for (i = 1; i < this.nestingLevel; ++i)@b@          this.methodParameter.increaseNestingLevel();@b@      }@b@    }@b@    catch (Throwable ex)@b@    {@b@      throw new IllegalStateException("Could not find original class structure", ex);@b@    }@b@  }@b@}